@rulab/adminjs-components 0.0.3 → 0.0.4
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/dist/bundle.js +8 -0
- package/dist/components/CustomSlug/CustomSlug.jsx +29 -0
- package/dist/components/CustomSlug/index.js +1 -0
- package/dist/components/CustomSlug/styles.js +15 -0
- package/dist/components/Editor/config.js +11 -0
- package/dist/components/Editor/index.js +1 -0
- package/dist/components/Editor/styles.js +64 -0
- package/dist/components/StringList/SortableList/SortableList.jsx +43 -0
- package/dist/components/StringList/SortableList/components/SortableItem/DragHandle.jsx +10 -0
- package/dist/components/StringList/SortableList/components/SortableItem/SortableItem.jsx +32 -0
- package/dist/components/StringList/SortableList/components/SortableItem/styles.js +20 -0
- package/dist/components/StringList/SortableList/components/SortableItem/types.js +1 -0
- package/dist/components/StringList/SortableList/components/index.js +2 -0
- package/dist/components/StringList/SortableList/index.js +1 -0
- package/dist/components/StringList/SortableList/styles.js +8 -0
- package/dist/components/StringList/StringList.jsx +67 -0
- package/dist/components/StringList/index.js +1 -0
- package/dist/components/StringList/styles.js +16 -0
- package/dist/components/index.js +3 -0
- package/dist/editorFeature.js +16 -0
- package/dist/index.cjs +33 -8
- package/dist/index.d.cts +6 -1
- package/dist/index.d.mts +8 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +32 -8
- package/dist/index.mjs +37 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/slugifyImport.js +3 -0
- package/dist/utils/slugifyTitle.js +10 -0
- package/package.json +2 -1
- package/src/components/CustomSlug/CustomSlug.tsx +4 -2
- package/src/components/Editor/Editor.jsx +2 -1
- package/src/components/Editor/EditorShow.jsx +22 -0
- package/src/components/Editor/index.ts +2 -1
- package/src/components/index.ts +2 -1
- package/src/utils/parseHtml.ts +12 -0
- package/src/utils/slugifyTitle.ts +1 -1
package/dist/bundle.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import * as url from "url";
|
|
3
|
+
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
|
4
|
+
const bundleComponent = (loader, componentName) => {
|
|
5
|
+
const componentPath = path.join(__dirname, `./components/${componentName}`);
|
|
6
|
+
return loader.add(componentName, componentPath);
|
|
7
|
+
};
|
|
8
|
+
export default bundleComponent;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React, { useEffect, useState, } from "react";
|
|
2
|
+
import { ThemeProvider } from "styled-components";
|
|
3
|
+
import { theme, Label } from "@adminjs/design-system";
|
|
4
|
+
import { slugifyTitle } from "../../utils/index.js";
|
|
5
|
+
import { StyledInputWrapper, StyledCustomInput, StyledGenerateButton, } from "./styles.js";
|
|
6
|
+
const CustomSlug = ({ property, record, onChange }) => {
|
|
7
|
+
const [inputValue, setInputValue] = useState(record.params.slug);
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
onChange(property.path, inputValue);
|
|
10
|
+
}, [inputValue]);
|
|
11
|
+
return (<ThemeProvider theme={theme}>
|
|
12
|
+
<Label htmlFor="customSlug">Slug</Label>
|
|
13
|
+
<StyledInputWrapper>
|
|
14
|
+
<StyledCustomInput id={property.path} name={property.path} value={inputValue} onChange={handleInput}/>
|
|
15
|
+
<StyledGenerateButton variant="outlined" onClick={generateSlug}>
|
|
16
|
+
Generate Slug
|
|
17
|
+
</StyledGenerateButton>
|
|
18
|
+
</StyledInputWrapper>
|
|
19
|
+
</ThemeProvider>);
|
|
20
|
+
function handleInput(e) {
|
|
21
|
+
setInputValue(e.target.value);
|
|
22
|
+
}
|
|
23
|
+
function generateSlug(e) {
|
|
24
|
+
e.preventDefault();
|
|
25
|
+
const title = record.title;
|
|
26
|
+
setInputValue(slugifyTitle(title));
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
export default CustomSlug;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "./CustomSlug.js";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// @ts-ignore
|
|
2
|
+
import { styled } from "@adminjs/design-system/styled-components";
|
|
3
|
+
// @ts-ignore
|
|
4
|
+
import { Button, Box, Input } from "@adminjs/design-system";
|
|
5
|
+
export const StyledInputWrapper = styled(Box) `
|
|
6
|
+
display: flex;
|
|
7
|
+
margin-bottom: 40px;
|
|
8
|
+
`;
|
|
9
|
+
export const StyledCustomInput = styled(Input) `
|
|
10
|
+
width: 100%;
|
|
11
|
+
margin-right: 10px;
|
|
12
|
+
`;
|
|
13
|
+
export const StyledGenerateButton = styled(Button) `
|
|
14
|
+
white-space: nowrap;
|
|
15
|
+
`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "./Editor.jsx";
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Box } from "@adminjs/design-system";
|
|
2
|
+
import { styled } from "@adminjs/design-system/styled-components";
|
|
3
|
+
export const Label = styled.div `
|
|
4
|
+
font-size: 12px;
|
|
5
|
+
margin-bottom: 8px;
|
|
6
|
+
`;
|
|
7
|
+
export const EditorWrapper = styled(Box) `
|
|
8
|
+
padding: 12px;
|
|
9
|
+
border: 1px solid rgb(187, 195, 203);
|
|
10
|
+
`;
|
|
11
|
+
export const StyledEditor = styled.div `
|
|
12
|
+
.cdx-block,
|
|
13
|
+
.ce-header {
|
|
14
|
+
padding-left: 58px;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.cdx-list {
|
|
18
|
+
padding-left: 85px;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.ce-block__content {
|
|
22
|
+
width: 100%;
|
|
23
|
+
max-width: none;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.ce-toolbar__content {
|
|
27
|
+
max-width: none;
|
|
28
|
+
left: 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.ce-toolbar__actions {
|
|
32
|
+
left: 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
h1.ce-header {
|
|
36
|
+
font-size: 22px;
|
|
37
|
+
font-weight: bold;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
h2.ce-header {
|
|
41
|
+
font-size: 20px;
|
|
42
|
+
font-weight: bold;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
h3.ce-header {
|
|
46
|
+
font-size: 18px;
|
|
47
|
+
font-weight: bold;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
h4.ce-header {
|
|
51
|
+
font-size: 16px;
|
|
52
|
+
font-weight: bold;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
h5.ce-header {
|
|
56
|
+
font-size: 15px;
|
|
57
|
+
font-weight: bold;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
h6.ce-header {
|
|
61
|
+
font-size: 14px;
|
|
62
|
+
font-weight: bold;
|
|
63
|
+
}
|
|
64
|
+
`;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React, { Fragment, useMemo, useState } from 'react';
|
|
2
|
+
import { DndContext, KeyboardSensor, PointerSensor, useSensor, useSensors, DragOverlay, defaultDropAnimationSideEffects, } from '@dnd-kit/core';
|
|
3
|
+
import { SortableContext, arrayMove, sortableKeyboardCoordinates, verticalListSortingStrategy, } from '@dnd-kit/sortable';
|
|
4
|
+
import { SortableItem } from './components/index.js';
|
|
5
|
+
import { StyledListWrapper } from './styles.js';
|
|
6
|
+
const dropAnimationConfig = {
|
|
7
|
+
sideEffects: defaultDropAnimationSideEffects({
|
|
8
|
+
styles: {
|
|
9
|
+
active: {
|
|
10
|
+
opacity: '0.4',
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
}),
|
|
14
|
+
};
|
|
15
|
+
export function SortableList({ items, onChange, renderItem, }) {
|
|
16
|
+
const [active, setActive] = useState(null);
|
|
17
|
+
const activeItem = useMemo(() => items.find((item) => item.id === active?.id), [active, items]);
|
|
18
|
+
const sensors = useSensors(useSensor(PointerSensor), useSensor(KeyboardSensor, {
|
|
19
|
+
coordinateGetter: sortableKeyboardCoordinates,
|
|
20
|
+
}));
|
|
21
|
+
return (<DndContext sensors={sensors} onDragStart={({ active }) => {
|
|
22
|
+
setActive(active);
|
|
23
|
+
}} onDragEnd={({ active, over }) => {
|
|
24
|
+
if (over && active.id !== over?.id) {
|
|
25
|
+
const activeIndex = items.findIndex(({ id }) => id === active.id);
|
|
26
|
+
const overIndex = items.findIndex(({ id }) => id === over.id);
|
|
27
|
+
onChange(arrayMove(items, activeIndex, overIndex));
|
|
28
|
+
}
|
|
29
|
+
setActive(null);
|
|
30
|
+
}} onDragCancel={() => {
|
|
31
|
+
setActive(null);
|
|
32
|
+
}}>
|
|
33
|
+
<SortableContext items={items} strategy={verticalListSortingStrategy}>
|
|
34
|
+
<StyledListWrapper role="application">
|
|
35
|
+
{items.map((item, index) => (<Fragment key={index}>{renderItem(item)}</Fragment>))}
|
|
36
|
+
</StyledListWrapper>
|
|
37
|
+
</SortableContext>
|
|
38
|
+
<DragOverlay dropAnimation={dropAnimationConfig}>
|
|
39
|
+
{activeItem ? renderItem(activeItem) : null}
|
|
40
|
+
</DragOverlay>
|
|
41
|
+
</DndContext>);
|
|
42
|
+
}
|
|
43
|
+
SortableList.Item = SortableItem;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React, { useContext } from 'react';
|
|
2
|
+
import { DragButton } from './styles.js';
|
|
3
|
+
export const DragHandle = ({ context }) => {
|
|
4
|
+
const { attributes, listeners, ref } = useContext(context);
|
|
5
|
+
return (<DragButton {...attributes} {...listeners} ref={ref}>
|
|
6
|
+
<svg viewBox="0 0 20 20" width="13">
|
|
7
|
+
<path d="M7 2a2 2 0 1 0 .001 4.001A2 2 0 0 0 7 2zm0 6a2 2 0 1 0 .001 4.001A2 2 0 0 0 7 8zm0 6a2 2 0 1 0 .001 4.001A2 2 0 0 0 7 14zm6-8a2 2 0 1 0-.001-4.001A2 2 0 0 0 13 6zm0 2a2 2 0 1 0 .001 4.001A2 2 0 0 0 13 8zm0 6a2 2 0 1 0 .001 4.001A2 2 0 0 0 13 14z"></path>
|
|
8
|
+
</svg>
|
|
9
|
+
</DragButton>);
|
|
10
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React, { createContext, useMemo } from 'react';
|
|
2
|
+
import { useSortable } from '@dnd-kit/sortable';
|
|
3
|
+
import { Button, Icon } from '@adminjs/design-system';
|
|
4
|
+
import { DragHandle } from './DragHandle.js';
|
|
5
|
+
import { StyledListItem } from './styles.js';
|
|
6
|
+
const SortableItemContext = createContext({
|
|
7
|
+
attributes: {},
|
|
8
|
+
listeners: undefined,
|
|
9
|
+
ref() { },
|
|
10
|
+
});
|
|
11
|
+
export function SortableItem({ children, id, onDelete, }) {
|
|
12
|
+
const { attributes, isDragging, listeners, setNodeRef, setActivatorNodeRef } = useSortable({ id });
|
|
13
|
+
const context = useMemo(() => ({
|
|
14
|
+
attributes,
|
|
15
|
+
listeners,
|
|
16
|
+
ref: setActivatorNodeRef,
|
|
17
|
+
}), [attributes, listeners, setActivatorNodeRef]);
|
|
18
|
+
const style = {
|
|
19
|
+
opacity: isDragging ? 0.4 : undefined,
|
|
20
|
+
};
|
|
21
|
+
return (<SortableItemContext.Provider value={context}>
|
|
22
|
+
<StyledListItem ref={setNodeRef} style={style}>
|
|
23
|
+
<div>
|
|
24
|
+
<DragHandle context={SortableItemContext}/>
|
|
25
|
+
{children}
|
|
26
|
+
</div>
|
|
27
|
+
<Button variant="outlined" color="danger" size="icon" onClick={(e) => onDelete(e, id)}>
|
|
28
|
+
<Icon icon="X" color="red"/>
|
|
29
|
+
</Button>
|
|
30
|
+
</StyledListItem>
|
|
31
|
+
</SortableItemContext.Provider>);
|
|
32
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { styled } from '@adminjs/design-system/styled-components';
|
|
2
|
+
export const StyledListItem = styled.li `
|
|
3
|
+
display: flex;
|
|
4
|
+
justify-content: space-between;
|
|
5
|
+
align-items: center;
|
|
6
|
+
background-color: #fff;
|
|
7
|
+
padding: 10px 20px 10px 15px;
|
|
8
|
+
box-shadow:
|
|
9
|
+
0 0 0 calc(1px / var(--scale-x, 1)) rgba(63, 63, 68, 0.05),
|
|
10
|
+
0 1px calc(3px / var(--scale-x, 1)) 0 rgba(34, 33, 81, 0.15);
|
|
11
|
+
border-radius: 5px;
|
|
12
|
+
list-style: none;
|
|
13
|
+
`;
|
|
14
|
+
export const DragButton = styled.button `
|
|
15
|
+
padding: 3px;
|
|
16
|
+
margin-right: 15px;
|
|
17
|
+
cursor: move;
|
|
18
|
+
background: none;
|
|
19
|
+
border: none;
|
|
20
|
+
`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SortableList } from './SortableList.js';
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import React, { useState, useEffect, } from "react";
|
|
2
|
+
import { ThemeProvider } from "styled-components";
|
|
3
|
+
import { theme, Button, Input, Label } from "@adminjs/design-system";
|
|
4
|
+
import { StyledWrapper, StyledCustomInput, StyledListWrapper, StyledInputWrapper, } from "./styles.js";
|
|
5
|
+
import { SortableList } from "./SortableList/SortableList.js";
|
|
6
|
+
const StringList = ({ record, onChange, property }) => {
|
|
7
|
+
const stringListValue = record.params?.[property.path] ?? property.props.value ?? "";
|
|
8
|
+
const initialList = stringListValue
|
|
9
|
+
? prepareDataForList(stringListValue)
|
|
10
|
+
: [];
|
|
11
|
+
const [inputValue, setInputValue] = useState("");
|
|
12
|
+
const [list, setList] = useState(initialList);
|
|
13
|
+
const serializedData = prepareDataForDatabase(list);
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
onChange(property.path, serializedData);
|
|
16
|
+
}, [serializedData]);
|
|
17
|
+
return (<ThemeProvider theme={theme}>
|
|
18
|
+
<Label htmlFor="custom">String List</Label>
|
|
19
|
+
<StyledWrapper>
|
|
20
|
+
<StyledListWrapper>
|
|
21
|
+
<SortableList items={list} onChange={setList} renderItem={(item) => (<SortableList.Item id={item.id} onDelete={handleDeleteButton}>
|
|
22
|
+
{item.value}
|
|
23
|
+
</SortableList.Item>)}/>
|
|
24
|
+
</StyledListWrapper>
|
|
25
|
+
<StyledInputWrapper>
|
|
26
|
+
<Input id="stringList" name={property.path} value={serializedData} hidden/>
|
|
27
|
+
<StyledCustomInput id="custom" name="customInput" value={inputValue} onChange={handleInput} onKeyPress={handleEnterPress}/>
|
|
28
|
+
<Button variant="outlined" onClick={handleAddButton}>
|
|
29
|
+
Add
|
|
30
|
+
</Button>
|
|
31
|
+
</StyledInputWrapper>
|
|
32
|
+
</StyledWrapper>
|
|
33
|
+
</ThemeProvider>);
|
|
34
|
+
function handleInput(e) {
|
|
35
|
+
setInputValue(e.target.value);
|
|
36
|
+
}
|
|
37
|
+
function handleEnterPress(e) {
|
|
38
|
+
if (e.key === "Enter") {
|
|
39
|
+
handleAddButton(e);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function handleAddButton(e) {
|
|
43
|
+
e.preventDefault();
|
|
44
|
+
if (Boolean(inputValue)) {
|
|
45
|
+
setList([...list, createListObject(inputValue)]);
|
|
46
|
+
setInputValue("");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function handleDeleteButton(e, id) {
|
|
50
|
+
e.preventDefault();
|
|
51
|
+
const newData = list.filter((item) => item.id !== id);
|
|
52
|
+
setList(newData);
|
|
53
|
+
}
|
|
54
|
+
function prepareDataForDatabase(list) {
|
|
55
|
+
return list.map(({ value }) => value).join("|");
|
|
56
|
+
}
|
|
57
|
+
function prepareDataForList(str) {
|
|
58
|
+
return str.split("|").map((item) => createListObject(item));
|
|
59
|
+
}
|
|
60
|
+
function createListObject(value) {
|
|
61
|
+
return {
|
|
62
|
+
id: `${Date.now()}-${Math.floor(Math.random() * 1000)}`,
|
|
63
|
+
value: value,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
export default StringList;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "./StringList.js";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { styled } from "@adminjs/design-system/styled-components";
|
|
2
|
+
import { Box, Input } from "@adminjs/design-system";
|
|
3
|
+
export const StyledWrapper = styled(Box) `
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
`;
|
|
7
|
+
export const StyledCustomInput = styled(Input) `
|
|
8
|
+
width: 100%;
|
|
9
|
+
margin-right: 10px;
|
|
10
|
+
`;
|
|
11
|
+
export const StyledInputWrapper = styled(Box) `
|
|
12
|
+
display: flex;
|
|
13
|
+
`;
|
|
14
|
+
export const StyledListWrapper = styled(Box) `
|
|
15
|
+
margin-bottom: 15px;
|
|
16
|
+
`;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { buildFeature, } from "adminjs";
|
|
2
|
+
import bundleComponent from "./bundle.js";
|
|
3
|
+
const editorFeature = (options) => {
|
|
4
|
+
const { componentLoader, name } = options;
|
|
5
|
+
const editComponent = bundleComponent(componentLoader, "Editor");
|
|
6
|
+
return buildFeature({
|
|
7
|
+
properties: {
|
|
8
|
+
[name]: {
|
|
9
|
+
components: {
|
|
10
|
+
edit: editComponent,
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
export default editorFeature;
|
package/dist/index.cjs
CHANGED
|
@@ -32,6 +32,7 @@ var src_exports = {};
|
|
|
32
32
|
__export(src_exports, {
|
|
33
33
|
CustomSlug: () => CustomSlug_default,
|
|
34
34
|
Editor: () => Editor_default,
|
|
35
|
+
EditorShow: () => EditorShow_default,
|
|
35
36
|
StringList: () => StringList_default
|
|
36
37
|
});
|
|
37
38
|
module.exports = __toCommonJS(src_exports);
|
|
@@ -49,7 +50,7 @@ var slugifyImport_default = import_slugify.default;
|
|
|
49
50
|
var slugifyTitle = (title) => {
|
|
50
51
|
return slugifyImport_default(title, {
|
|
51
52
|
replacement: "-",
|
|
52
|
-
remove:
|
|
53
|
+
remove: /[*+~.()'"!:@]/g,
|
|
53
54
|
lower: true,
|
|
54
55
|
locale: "vi",
|
|
55
56
|
trim: true
|
|
@@ -91,8 +92,10 @@ var CustomSlug = ({ property, record, onChange }) => {
|
|
|
91
92
|
}
|
|
92
93
|
function generateSlug(e) {
|
|
93
94
|
e.preventDefault();
|
|
94
|
-
const title = record.title;
|
|
95
|
-
|
|
95
|
+
const title = record.params.title;
|
|
96
|
+
if (title) {
|
|
97
|
+
setInputValue(slugifyTitle(title));
|
|
98
|
+
}
|
|
96
99
|
}
|
|
97
100
|
};
|
|
98
101
|
var CustomSlug_default = CustomSlug;
|
|
@@ -416,10 +419,7 @@ var EDITOR_TOOLS = {
|
|
|
416
419
|
// src/components/Editor/Editor.jsx
|
|
417
420
|
var Editor = ({ property, record, onChangeAdmin, editorId }) => {
|
|
418
421
|
const [jsonData, setJsonData] = (0, import_react6.useState)();
|
|
419
|
-
|
|
420
|
-
record.params[property.path],
|
|
421
|
-
"record.params[property.path].path"
|
|
422
|
-
);
|
|
422
|
+
const isSavedData = Boolean(record.params[property.path]);
|
|
423
423
|
const ref = (0, import_react6.useRef)();
|
|
424
424
|
(0, import_react6.useEffect)(() => {
|
|
425
425
|
onChangeAdmin(property.path, jsonData);
|
|
@@ -429,7 +429,7 @@ var Editor = ({ property, record, onChangeAdmin, editorId }) => {
|
|
|
429
429
|
const editor = new import_editorjs.default({
|
|
430
430
|
holder: editorId,
|
|
431
431
|
tools: EDITOR_TOOLS,
|
|
432
|
-
data: JSON.parse(record.params[property.path]),
|
|
432
|
+
data: isSavedData ? JSON.parse(record.params[property.path]) : "",
|
|
433
433
|
async onChange(api, event) {
|
|
434
434
|
const data = await api.saver.save();
|
|
435
435
|
setJsonData(JSON.stringify(data));
|
|
@@ -444,9 +444,34 @@ var Editor = ({ property, record, onChangeAdmin, editorId }) => {
|
|
|
444
444
|
return /* @__PURE__ */ import_react6.default.createElement(import_styled_components8.ThemeProvider, { theme: import_design_system7.theme }, /* @__PURE__ */ import_react6.default.createElement(Label3, null, "Text"), /* @__PURE__ */ import_react6.default.createElement(EditorWrapper, null, /* @__PURE__ */ import_react6.default.createElement(StyledEditor, { id: editorId })));
|
|
445
445
|
};
|
|
446
446
|
var Editor_default = Editor;
|
|
447
|
+
|
|
448
|
+
// src/components/Editor/EditorShow.jsx
|
|
449
|
+
var import_react7 = __toESM(require("react"), 1);
|
|
450
|
+
var import_styled_components9 = require("styled-components");
|
|
451
|
+
var import_design_system8 = require("@adminjs/design-system");
|
|
452
|
+
|
|
453
|
+
// src/utils/parseHtml.ts
|
|
454
|
+
var import_editorjs_html = __toESM(require("editorjs-html"), 1);
|
|
455
|
+
var parseHtml = (jsonData) => {
|
|
456
|
+
const edjsParser = (0, import_editorjs_html.default)();
|
|
457
|
+
try {
|
|
458
|
+
const data = edjsParser.parse(JSON.parse(String(jsonData)));
|
|
459
|
+
return String(data).replace(/>,</g, "><");
|
|
460
|
+
} catch (e) {
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
// src/components/Editor/EditorShow.jsx
|
|
466
|
+
var EditorShow = ({ property, record }) => {
|
|
467
|
+
const htmlContent = parseHtml(record.params[property.path]);
|
|
468
|
+
return /* @__PURE__ */ import_react7.default.createElement(import_styled_components9.ThemeProvider, { theme: import_design_system8.theme }, /* @__PURE__ */ import_react7.default.createElement(Label3, null, "Content"), htmlContent && /* @__PURE__ */ import_react7.default.createElement("div", { dangerouslySetInnerHTML: { __html: String(htmlContent) } }));
|
|
469
|
+
};
|
|
470
|
+
var EditorShow_default = EditorShow;
|
|
447
471
|
// Annotate the CommonJS export names for ESM import in node:
|
|
448
472
|
0 && (module.exports = {
|
|
449
473
|
CustomSlug,
|
|
450
474
|
Editor,
|
|
475
|
+
EditorShow,
|
|
451
476
|
StringList
|
|
452
477
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -14,4 +14,9 @@ declare function Editor({ property, record, onChangeAdmin, editorId }: {
|
|
|
14
14
|
editorId: any;
|
|
15
15
|
}): React.JSX.Element;
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
declare function EditorShow({ property, record }: {
|
|
18
|
+
property: any;
|
|
19
|
+
record: any;
|
|
20
|
+
}): React.JSX.Element;
|
|
21
|
+
|
|
22
|
+
export { CustomSlug, Editor, EditorShow, StringList };
|
package/dist/index.d.mts
ADDED
package/dist/index.d.ts
CHANGED
|
@@ -14,4 +14,9 @@ declare function Editor({ property, record, onChangeAdmin, editorId }: {
|
|
|
14
14
|
editorId: any;
|
|
15
15
|
}): React.JSX.Element;
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
declare function EditorShow({ property, record }: {
|
|
18
|
+
property: any;
|
|
19
|
+
record: any;
|
|
20
|
+
}): React.JSX.Element;
|
|
21
|
+
|
|
22
|
+
export { CustomSlug, Editor, EditorShow, StringList };
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var slugifyImport_default = slugify;
|
|
|
14
14
|
var slugifyTitle = (title) => {
|
|
15
15
|
return slugifyImport_default(title, {
|
|
16
16
|
replacement: "-",
|
|
17
|
-
remove:
|
|
17
|
+
remove: /[*+~.()'"!:@]/g,
|
|
18
18
|
lower: true,
|
|
19
19
|
locale: "vi",
|
|
20
20
|
trim: true
|
|
@@ -56,8 +56,10 @@ var CustomSlug = ({ property, record, onChange }) => {
|
|
|
56
56
|
}
|
|
57
57
|
function generateSlug(e) {
|
|
58
58
|
e.preventDefault();
|
|
59
|
-
const title = record.title;
|
|
60
|
-
|
|
59
|
+
const title = record.params.title;
|
|
60
|
+
if (title) {
|
|
61
|
+
setInputValue(slugifyTitle(title));
|
|
62
|
+
}
|
|
61
63
|
}
|
|
62
64
|
};
|
|
63
65
|
var CustomSlug_default = CustomSlug;
|
|
@@ -397,10 +399,7 @@ var EDITOR_TOOLS = {
|
|
|
397
399
|
// src/components/Editor/Editor.jsx
|
|
398
400
|
var Editor = ({ property, record, onChangeAdmin, editorId }) => {
|
|
399
401
|
const [jsonData, setJsonData] = useState4();
|
|
400
|
-
|
|
401
|
-
record.params[property.path],
|
|
402
|
-
"record.params[property.path].path"
|
|
403
|
-
);
|
|
402
|
+
const isSavedData = Boolean(record.params[property.path]);
|
|
404
403
|
const ref = useRef();
|
|
405
404
|
useEffect3(() => {
|
|
406
405
|
onChangeAdmin(property.path, jsonData);
|
|
@@ -410,7 +409,7 @@ var Editor = ({ property, record, onChangeAdmin, editorId }) => {
|
|
|
410
409
|
const editor = new EditorJS({
|
|
411
410
|
holder: editorId,
|
|
412
411
|
tools: EDITOR_TOOLS,
|
|
413
|
-
data: JSON.parse(record.params[property.path]),
|
|
412
|
+
data: isSavedData ? JSON.parse(record.params[property.path]) : "",
|
|
414
413
|
async onChange(api, event) {
|
|
415
414
|
const data = await api.saver.save();
|
|
416
415
|
setJsonData(JSON.stringify(data));
|
|
@@ -425,8 +424,33 @@ var Editor = ({ property, record, onChangeAdmin, editorId }) => {
|
|
|
425
424
|
return /* @__PURE__ */ React6.createElement(ThemeProvider3, { theme: theme3 }, /* @__PURE__ */ React6.createElement(Label3, null, "Text"), /* @__PURE__ */ React6.createElement(EditorWrapper, null, /* @__PURE__ */ React6.createElement(StyledEditor, { id: editorId })));
|
|
426
425
|
};
|
|
427
426
|
var Editor_default = Editor;
|
|
427
|
+
|
|
428
|
+
// src/components/Editor/EditorShow.jsx
|
|
429
|
+
import React7, { memo as memo2, useState as useState5, useEffect as useEffect4, useRef as useRef2 } from "react";
|
|
430
|
+
import { ThemeProvider as ThemeProvider4 } from "styled-components";
|
|
431
|
+
import { theme as theme4 } from "@adminjs/design-system";
|
|
432
|
+
|
|
433
|
+
// src/utils/parseHtml.ts
|
|
434
|
+
import edjsHTML from "editorjs-html";
|
|
435
|
+
var parseHtml = (jsonData) => {
|
|
436
|
+
const edjsParser = edjsHTML();
|
|
437
|
+
try {
|
|
438
|
+
const data = edjsParser.parse(JSON.parse(String(jsonData)));
|
|
439
|
+
return String(data).replace(/>,</g, "><");
|
|
440
|
+
} catch (e) {
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
// src/components/Editor/EditorShow.jsx
|
|
446
|
+
var EditorShow = ({ property, record }) => {
|
|
447
|
+
const htmlContent = parseHtml(record.params[property.path]);
|
|
448
|
+
return /* @__PURE__ */ React7.createElement(ThemeProvider4, { theme: theme4 }, /* @__PURE__ */ React7.createElement(Label3, null, "Content"), htmlContent && /* @__PURE__ */ React7.createElement("div", { dangerouslySetInnerHTML: { __html: String(htmlContent) } }));
|
|
449
|
+
};
|
|
450
|
+
var EditorShow_default = EditorShow;
|
|
428
451
|
export {
|
|
429
452
|
CustomSlug_default as CustomSlug,
|
|
430
453
|
Editor_default as Editor,
|
|
454
|
+
EditorShow_default as EditorShow,
|
|
431
455
|
StringList_default as StringList
|
|
432
456
|
};
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// src/features/editorFeature.ts
|
|
2
|
+
import {
|
|
3
|
+
buildFeature
|
|
4
|
+
} from "adminjs";
|
|
5
|
+
|
|
6
|
+
// src/bundle.ts
|
|
7
|
+
import path from "path";
|
|
8
|
+
import * as url from "url";
|
|
9
|
+
var __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
|
10
|
+
var bundle = (loader, componentName) => {
|
|
11
|
+
const componentPath = path.join(__dirname, `./components/${componentName}`);
|
|
12
|
+
return loader.add(componentName, componentPath);
|
|
13
|
+
};
|
|
14
|
+
var bundle_default = bundle;
|
|
15
|
+
|
|
16
|
+
// src/features/editorFeature.ts
|
|
17
|
+
var editorFeature = (options) => {
|
|
18
|
+
const { componentLoader } = options;
|
|
19
|
+
const editComponent = bundle_default(componentLoader, "Editor");
|
|
20
|
+
return buildFeature({
|
|
21
|
+
properties: {
|
|
22
|
+
editor: {
|
|
23
|
+
components: {
|
|
24
|
+
edit: editComponent
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
var editorFeature_default = editorFeature;
|
|
31
|
+
|
|
32
|
+
// src/index.ts
|
|
33
|
+
var src_default = editorFeature_default;
|
|
34
|
+
export {
|
|
35
|
+
src_default as default,
|
|
36
|
+
editorFeature_default as editorFeature
|
|
37
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { slugifyTitle } from "./slugifyTitle.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulab/adminjs-components",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"module": "dist/index.mjs",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"@editorjs/list": "^1.9.0",
|
|
26
26
|
"@editorjs/paragraph": "^2.11.6",
|
|
27
27
|
"adminjs": "^7.8.1",
|
|
28
|
+
"editorjs-html": "^3.4.3",
|
|
28
29
|
"react": "^18.2.0",
|
|
29
30
|
"slugify": "^1.6.6",
|
|
30
31
|
"styled-components": "^6.1.11"
|
|
@@ -50,8 +50,10 @@ const CustomSlug: FC<CustomSlugTypes> = ({ property, record, onChange }) => {
|
|
|
50
50
|
|
|
51
51
|
function generateSlug(e: SyntheticEvent<HTMLInputElement>) {
|
|
52
52
|
e.preventDefault();
|
|
53
|
-
const title = record.title;
|
|
54
|
-
|
|
53
|
+
const title = record.params.title;
|
|
54
|
+
if (title) {
|
|
55
|
+
setInputValue(slugifyTitle(title));
|
|
56
|
+
}
|
|
55
57
|
}
|
|
56
58
|
};
|
|
57
59
|
|
|
@@ -9,6 +9,7 @@ import { EDITOR_TOOLS } from "./config";
|
|
|
9
9
|
|
|
10
10
|
const Editor = ({ property, record, onChangeAdmin, editorId }) => {
|
|
11
11
|
const [jsonData, setJsonData] = useState();
|
|
12
|
+
const isSavedData = Boolean(record.params[property.path]);
|
|
12
13
|
|
|
13
14
|
const ref = useRef();
|
|
14
15
|
|
|
@@ -21,7 +22,7 @@ const Editor = ({ property, record, onChangeAdmin, editorId }) => {
|
|
|
21
22
|
const editor = new EditorJS({
|
|
22
23
|
holder: editorId,
|
|
23
24
|
tools: EDITOR_TOOLS,
|
|
24
|
-
data: JSON.parse(record.params[property.path]),
|
|
25
|
+
data: isSavedData ? JSON.parse(record.params[property.path]) : "",
|
|
25
26
|
async onChange(api, event) {
|
|
26
27
|
const data = await api.saver.save();
|
|
27
28
|
setJsonData(JSON.stringify(data));
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React, { memo, useState, useEffect, useRef } from "react";
|
|
2
|
+
import { ThemeProvider } from "styled-components";
|
|
3
|
+
import { theme } from "@adminjs/design-system";
|
|
4
|
+
|
|
5
|
+
import { parseHtml } from "../../utils/parseHtml";
|
|
6
|
+
|
|
7
|
+
import { Label } from "./styles";
|
|
8
|
+
|
|
9
|
+
const EditorShow = ({ property, record }) => {
|
|
10
|
+
const htmlContent = parseHtml(record.params[property.path]);
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<ThemeProvider theme={theme}>
|
|
14
|
+
<Label>Content</Label>
|
|
15
|
+
{htmlContent && (
|
|
16
|
+
<div dangerouslySetInnerHTML={{ __html: String(htmlContent) }} />
|
|
17
|
+
)}
|
|
18
|
+
</ThemeProvider>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default EditorShow;
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export
|
|
1
|
+
export * from "./Editor.jsx";
|
|
2
|
+
export * from "./EditorShow.jsx";
|
package/src/components/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { default as CustomSlug } from "./CustomSlug/CustomSlug.js";
|
|
2
2
|
export { default as StringList } from "./StringList/StringList.js";
|
|
3
|
-
export { default as Editor } from "./Editor";
|
|
3
|
+
export { default as Editor } from "./Editor/Editor.jsx";
|
|
4
|
+
export { default as EditorShow } from "./Editor/EditorShow.jsx";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import edjsHTML from "editorjs-html";
|
|
2
|
+
|
|
3
|
+
export const parseHtml = (jsonData?: string) => {
|
|
4
|
+
const edjsParser = edjsHTML();
|
|
5
|
+
|
|
6
|
+
try {
|
|
7
|
+
const data = edjsParser.parse(JSON.parse(String(jsonData)));
|
|
8
|
+
return String(data).replace(/>,</g, "><");
|
|
9
|
+
} catch (e) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
};
|