@dotcms/react 0.0.1-alpha.1 → 0.0.1-alpha.11
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/.babelrc +12 -0
- package/.eslintrc.json +18 -0
- package/README.md +16 -21
- package/jest.config.ts +11 -0
- package/package.json +27 -31
- package/project.json +51 -0
- package/src/{index.d.ts → index.ts} +4 -5
- package/src/lib/components/Column/Column.module.css +99 -0
- package/src/lib/components/Column/Column.spec.tsx +78 -0
- package/src/lib/components/Column/Column.tsx +45 -0
- package/src/lib/components/Container/Container.module.css +7 -0
- package/src/lib/components/Container/Container.spec.tsx +82 -0
- package/src/lib/components/Container/Container.tsx +106 -0
- package/src/lib/components/DotcmsLayout/DotcmsLayout.module.css +7 -0
- package/src/lib/components/DotcmsLayout/DotcmsLayout.spec.tsx +41 -0
- package/src/lib/components/DotcmsLayout/{DotcmsLayout.d.ts → DotcmsLayout.tsx} +48 -32
- package/src/lib/components/PageProvider/PageProvider.module.css +7 -0
- package/src/lib/components/PageProvider/PageProvider.spec.tsx +54 -0
- package/src/lib/components/PageProvider/{PageProvider.d.ts → PageProvider.tsx} +95 -81
- package/src/lib/components/Row/Row.module.css +5 -0
- package/src/lib/components/Row/Row.spec.tsx +92 -0
- package/src/lib/components/Row/Row.tsx +51 -0
- package/src/lib/contexts/PageContext.tsx +5 -0
- package/src/lib/hooks/useDotcmsEditor.spec.ts +56 -0
- package/src/lib/hooks/useDotcmsEditor.ts +29 -0
- package/src/lib/hooks/useDotcmsPageContext.spec.tsx +43 -0
- package/src/lib/hooks/{useDotcmsPageContext.d.ts → useDotcmsPageContext.tsx} +15 -9
- package/src/lib/mocks/{index.d.ts → index.ts} +1 -1
- package/src/lib/mocks/mockPageContext.tsx +84 -0
- package/src/lib/utils/utils.ts +69 -0
- package/tsconfig.json +20 -0
- package/tsconfig.lib.json +23 -0
- package/tsconfig.spec.json +20 -0
- package/index.js +0 -2413
- package/src/lib/components/Column/Column.d.ts +0 -7
- package/src/lib/components/Container/Container.d.ts +0 -6
- package/src/lib/components/Row/Row.d.ts +0 -25
- package/src/lib/contexts/PageContext.d.ts +0 -3
- package/src/lib/hooks/usePageEditor.d.ts +0 -48
- package/src/lib/mocks/mockPageContext.d.ts +0 -2
- package/src/lib/utils/utils.d.ts +0 -50
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { renderHook } from '@testing-library/react-hooks';
|
|
2
|
+
|
|
3
|
+
import * as dotcmsClient from '@dotcms/client';
|
|
4
|
+
|
|
5
|
+
import { useDotcmsEditor } from './useDotcmsEditor';
|
|
6
|
+
|
|
7
|
+
describe('useDotcmsEditor', () => {
|
|
8
|
+
let isInsideEditorSpy: jest.SpyInstance<boolean>;
|
|
9
|
+
let initEditorSpy: jest.SpyInstance<void>;
|
|
10
|
+
let destroyEditorSpy: jest.SpyInstance<void>;
|
|
11
|
+
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
isInsideEditorSpy = jest.spyOn(dotcmsClient, 'isInsideEditor');
|
|
14
|
+
initEditorSpy = jest.spyOn(dotcmsClient, 'initEditor');
|
|
15
|
+
destroyEditorSpy = jest.spyOn(dotcmsClient, 'destroyEditor');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
jest.clearAllMocks();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('should call initEditor when inside editor', () => {
|
|
23
|
+
isInsideEditorSpy.mockReturnValueOnce(true);
|
|
24
|
+
|
|
25
|
+
renderHook(() => useDotcmsEditor());
|
|
26
|
+
|
|
27
|
+
expect(initEditorSpy).toHaveBeenCalled();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should call destroyEditor on unmount when inside editor', () => {
|
|
31
|
+
isInsideEditorSpy.mockReturnValueOnce(true);
|
|
32
|
+
|
|
33
|
+
const { unmount } = renderHook(() => useDotcmsEditor());
|
|
34
|
+
|
|
35
|
+
unmount();
|
|
36
|
+
|
|
37
|
+
expect(destroyEditorSpy).toHaveBeenCalled();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should not call initEditor or destroyEditor when outside editor', () => {
|
|
41
|
+
isInsideEditorSpy.mockReturnValueOnce(false);
|
|
42
|
+
|
|
43
|
+
renderHook(() => useDotcmsEditor());
|
|
44
|
+
|
|
45
|
+
expect(initEditorSpy).not.toHaveBeenCalled();
|
|
46
|
+
expect(destroyEditorSpy).not.toHaveBeenCalled();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should call initEditor with options', () => {
|
|
50
|
+
isInsideEditorSpy.mockReturnValueOnce(true);
|
|
51
|
+
|
|
52
|
+
renderHook(() => useDotcmsEditor({ onReload: jest.fn() }));
|
|
53
|
+
|
|
54
|
+
expect(initEditorSpy).toHaveBeenCalledWith({ onReload: expect.any(Function) });
|
|
55
|
+
});
|
|
56
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
DotCMSPageEditorConfig,
|
|
5
|
+
destroyEditor,
|
|
6
|
+
initEditor,
|
|
7
|
+
isInsideEditor,
|
|
8
|
+
updateNavigation
|
|
9
|
+
} from '@dotcms/client';
|
|
10
|
+
export const useDotcmsEditor = (config?: DotCMSPageEditorConfig) => {
|
|
11
|
+
const [isInsideEditorPage, setIsInsideEditorPage] = useState(false);
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
const insideEditor = isInsideEditor();
|
|
14
|
+
if (insideEditor) {
|
|
15
|
+
initEditor(config);
|
|
16
|
+
updateNavigation(config?.pathname || '/');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
setIsInsideEditorPage(insideEditor);
|
|
20
|
+
|
|
21
|
+
return () => {
|
|
22
|
+
if (insideEditor) {
|
|
23
|
+
destroyEditor();
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}, [config]);
|
|
27
|
+
|
|
28
|
+
return isInsideEditorPage;
|
|
29
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { renderHook } from '@testing-library/react-hooks';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
import { useDotcmsPageContext } from './useDotcmsPageContext'; // Adjust the import path based on your file structure.
|
|
5
|
+
|
|
6
|
+
import { PageProviderContext } from '../components/PageProvider/PageProvider';
|
|
7
|
+
import { PageContext } from '../contexts/PageContext';
|
|
8
|
+
|
|
9
|
+
const mockContextValue: PageProviderContext = {
|
|
10
|
+
components: {},
|
|
11
|
+
containers: {},
|
|
12
|
+
layout: {
|
|
13
|
+
header: false,
|
|
14
|
+
footer: false,
|
|
15
|
+
body: {
|
|
16
|
+
rows: []
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
page: {
|
|
20
|
+
title: 'Test Page',
|
|
21
|
+
identifier: 'test-page'
|
|
22
|
+
},
|
|
23
|
+
viewAs: {
|
|
24
|
+
language: {
|
|
25
|
+
id: 'en'
|
|
26
|
+
},
|
|
27
|
+
persona: {
|
|
28
|
+
keyTag: 'persona'
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
describe('useDotcmsPageContext', () => {
|
|
34
|
+
it('returns the context value', () => {
|
|
35
|
+
const { result } = renderHook(() => useDotcmsPageContext(), {
|
|
36
|
+
wrapper: ({ children }: { children: ReactNode }) => (
|
|
37
|
+
<PageContext.Provider value={mockContextValue}>{children}</PageContext.Provider>
|
|
38
|
+
)
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
expect(result.current).toEqual(mockContextValue);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
*
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import { useContext } from 'react';
|
|
2
|
+
|
|
3
|
+
import { PageProviderContext } from '../components/PageProvider/PageProvider';
|
|
4
|
+
import { PageContext } from '../contexts/PageContext';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* `useDotcmsPageContext` is a custom React hook that provides access to the `PageProviderContext`.
|
|
8
|
+
* It takes no parameters and returns the context value or `null` if it's not available.
|
|
9
|
+
*
|
|
10
|
+
* @category Hooks
|
|
11
|
+
* @returns {PageProviderContext | null} - The context value or `null` if it's not available.
|
|
12
|
+
*/
|
|
13
|
+
export function useDotcmsPageContext() {
|
|
14
|
+
return useContext<PageProviderContext | null>(PageContext);
|
|
15
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from './mockPageContext';
|
|
1
|
+
export * from './mockPageContext';
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { PageProvider, PageProviderContext } from '../components/PageProvider/PageProvider';
|
|
2
|
+
|
|
3
|
+
export const mockPageContext: PageProviderContext = {
|
|
4
|
+
layout: {
|
|
5
|
+
header: true,
|
|
6
|
+
footer: true,
|
|
7
|
+
body: {
|
|
8
|
+
rows: [
|
|
9
|
+
{
|
|
10
|
+
styleClass: 'row',
|
|
11
|
+
columns: [
|
|
12
|
+
{
|
|
13
|
+
styleClass: 'col-md-12',
|
|
14
|
+
width: 6,
|
|
15
|
+
leftOffset: 3,
|
|
16
|
+
containers: [
|
|
17
|
+
{
|
|
18
|
+
identifier: 'container-1',
|
|
19
|
+
uuid: 'uuid-1'
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
containers: {
|
|
29
|
+
'container-1': {
|
|
30
|
+
container: {
|
|
31
|
+
path: 'path/to/container',
|
|
32
|
+
identifier: 'container-1',
|
|
33
|
+
maxContentlets: 100,
|
|
34
|
+
parentPermissionable: {}
|
|
35
|
+
},
|
|
36
|
+
containerStructures: [
|
|
37
|
+
{
|
|
38
|
+
contentTypeVar: 'content-type-1'
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
contentlets: {
|
|
42
|
+
'uuid-1': [
|
|
43
|
+
{
|
|
44
|
+
contentType: 'content-type-1',
|
|
45
|
+
identifier: 'contentlet-1',
|
|
46
|
+
title: 'Contentlet 1',
|
|
47
|
+
inode: 'inode-1',
|
|
48
|
+
onNumberOfPages: 1
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
'container-2': {
|
|
54
|
+
container: {
|
|
55
|
+
path: 'path/to/container',
|
|
56
|
+
identifier: 'container-2',
|
|
57
|
+
maxContentlets: 100,
|
|
58
|
+
parentPermissionable: {}
|
|
59
|
+
},
|
|
60
|
+
containerStructures: [
|
|
61
|
+
{
|
|
62
|
+
contentTypeVar: 'content-type-2'
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
contentlets: {
|
|
66
|
+
'uuid-2': []
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
page: { identifier: 'page-1', title: 'Hello Page' },
|
|
71
|
+
viewAs: { language: { id: 'en' }, persona: { keyTag: 'persona-1' } },
|
|
72
|
+
components: {},
|
|
73
|
+
isInsideEditor: false
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const MockContextRender = ({
|
|
77
|
+
children,
|
|
78
|
+
mockContext
|
|
79
|
+
}: {
|
|
80
|
+
children: JSX.Element;
|
|
81
|
+
mockContext: Partial<PageProviderContext>;
|
|
82
|
+
}) => {
|
|
83
|
+
return <PageProvider entity={mockContext}>{children}</PageProvider>;
|
|
84
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { ContainerData, PageProviderContext } from '../components/PageProvider/PageProvider';
|
|
2
|
+
|
|
3
|
+
const endClassMap: Record<number, string> = {
|
|
4
|
+
1: 'col-end-1',
|
|
5
|
+
2: 'col-end-2',
|
|
6
|
+
3: 'col-end-3',
|
|
7
|
+
4: 'col-end-4',
|
|
8
|
+
5: 'col-end-5',
|
|
9
|
+
6: 'col-end-6',
|
|
10
|
+
7: 'col-end-7',
|
|
11
|
+
8: 'col-end-8',
|
|
12
|
+
9: 'col-end-9',
|
|
13
|
+
10: 'col-end-10',
|
|
14
|
+
11: 'col-end-11',
|
|
15
|
+
12: 'col-end-12',
|
|
16
|
+
13: 'col-end-13'
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const startClassMap: Record<number, string> = {
|
|
20
|
+
1: 'col-start-1',
|
|
21
|
+
2: 'col-start-2',
|
|
22
|
+
3: 'col-start-3',
|
|
23
|
+
4: 'col-start-4',
|
|
24
|
+
5: 'col-start-5',
|
|
25
|
+
6: 'col-start-6',
|
|
26
|
+
7: 'col-start-7',
|
|
27
|
+
8: 'col-start-8',
|
|
28
|
+
9: 'col-start-9',
|
|
29
|
+
10: 'col-start-10',
|
|
30
|
+
11: 'col-start-11',
|
|
31
|
+
12: 'col-start-12'
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const getContainersData = (
|
|
35
|
+
containers: ContainerData,
|
|
36
|
+
containerRef: PageProviderContext['layout']['body']['rows'][0]['columns'][0]['containers'][0]
|
|
37
|
+
) => {
|
|
38
|
+
const { identifier, uuid } = containerRef;
|
|
39
|
+
|
|
40
|
+
const { containerStructures, container } = containers[identifier];
|
|
41
|
+
|
|
42
|
+
// Get the variant id
|
|
43
|
+
const { variantId } = container?.parentPermissionable || {};
|
|
44
|
+
|
|
45
|
+
// Get accepts types of content types for this container
|
|
46
|
+
const acceptTypes = containerStructures.map((structure) => structure.contentTypeVar).join(',');
|
|
47
|
+
|
|
48
|
+
// Get the contentlets for "this" container
|
|
49
|
+
const contentlets = containers[identifier].contentlets[`uuid-${uuid}`];
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
...containers[identifier].container,
|
|
53
|
+
acceptTypes,
|
|
54
|
+
contentlets,
|
|
55
|
+
variantId
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const combineClasses = (classes: string[]) => classes.filter(Boolean).join(' ');
|
|
60
|
+
|
|
61
|
+
export const getPositionStyleClasses = (start: number, end: number) => {
|
|
62
|
+
const startClass = startClassMap[start];
|
|
63
|
+
const endClass = endClassMap[end];
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
startClass,
|
|
67
|
+
endClass
|
|
68
|
+
};
|
|
69
|
+
};
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"jsx": "react-jsx",
|
|
4
|
+
"allowJs": false,
|
|
5
|
+
"esModuleInterop": false,
|
|
6
|
+
"allowSyntheticDefaultImports": true,
|
|
7
|
+
"strict": true
|
|
8
|
+
},
|
|
9
|
+
"files": [],
|
|
10
|
+
"include": [],
|
|
11
|
+
"references": [
|
|
12
|
+
{
|
|
13
|
+
"path": "./tsconfig.lib.json"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"path": "./tsconfig.spec.json"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"extends": "../../../tsconfig.base.json"
|
|
20
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "../../../dist/out-tsc",
|
|
5
|
+
"types": ["node"]
|
|
6
|
+
},
|
|
7
|
+
"files": [
|
|
8
|
+
"../../../node_modules/@nrwl/react/typings/cssmodule.d.ts",
|
|
9
|
+
"../../../node_modules/@nrwl/react/typings/image.d.ts"
|
|
10
|
+
],
|
|
11
|
+
"exclude": [
|
|
12
|
+
"jest.config.ts",
|
|
13
|
+
"src/**/*.spec.ts",
|
|
14
|
+
"src/**/*.test.ts",
|
|
15
|
+
"src/**/*.spec.tsx",
|
|
16
|
+
"src/**/*.test.tsx",
|
|
17
|
+
"src/**/*.spec.js",
|
|
18
|
+
"src/**/*.test.js",
|
|
19
|
+
"src/**/*.spec.jsx",
|
|
20
|
+
"src/**/*.test.jsx"
|
|
21
|
+
],
|
|
22
|
+
"include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"]
|
|
23
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "../../../dist/out-tsc",
|
|
5
|
+
"module": "commonjs",
|
|
6
|
+
"types": ["jest", "node"]
|
|
7
|
+
},
|
|
8
|
+
"include": [
|
|
9
|
+
"jest.config.ts",
|
|
10
|
+
"src/**/*.test.ts",
|
|
11
|
+
"src/**/*.spec.ts",
|
|
12
|
+
"src/**/*.test.tsx",
|
|
13
|
+
"src/**/*.spec.tsx",
|
|
14
|
+
"src/**/*.test.js",
|
|
15
|
+
"src/**/*.spec.js",
|
|
16
|
+
"src/**/*.test.jsx",
|
|
17
|
+
"src/**/*.spec.jsx",
|
|
18
|
+
"src/**/*.d.ts"
|
|
19
|
+
]
|
|
20
|
+
}
|