@rulab/adminjs-components 0.0.2 → 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 -4
- 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 -4
- 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,6 +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)();
|
|
422
|
+
const isSavedData = Boolean(record.params[property.path]);
|
|
419
423
|
const ref = (0, import_react6.useRef)();
|
|
420
424
|
(0, import_react6.useEffect)(() => {
|
|
421
425
|
onChangeAdmin(property.path, jsonData);
|
|
@@ -425,7 +429,7 @@ var Editor = ({ property, record, onChangeAdmin, editorId }) => {
|
|
|
425
429
|
const editor = new import_editorjs.default({
|
|
426
430
|
holder: editorId,
|
|
427
431
|
tools: EDITOR_TOOLS,
|
|
428
|
-
data: JSON.parse(record.params.
|
|
432
|
+
data: isSavedData ? JSON.parse(record.params[property.path]) : "",
|
|
429
433
|
async onChange(api, event) {
|
|
430
434
|
const data = await api.saver.save();
|
|
431
435
|
setJsonData(JSON.stringify(data));
|
|
@@ -440,9 +444,34 @@ var Editor = ({ property, record, onChangeAdmin, editorId }) => {
|
|
|
440
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 })));
|
|
441
445
|
};
|
|
442
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;
|
|
443
471
|
// Annotate the CommonJS export names for ESM import in node:
|
|
444
472
|
0 && (module.exports = {
|
|
445
473
|
CustomSlug,
|
|
446
474
|
Editor,
|
|
475
|
+
EditorShow,
|
|
447
476
|
StringList
|
|
448
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,6 +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();
|
|
402
|
+
const isSavedData = Boolean(record.params[property.path]);
|
|
400
403
|
const ref = useRef();
|
|
401
404
|
useEffect3(() => {
|
|
402
405
|
onChangeAdmin(property.path, jsonData);
|
|
@@ -406,7 +409,7 @@ var Editor = ({ property, record, onChangeAdmin, editorId }) => {
|
|
|
406
409
|
const editor = new EditorJS({
|
|
407
410
|
holder: editorId,
|
|
408
411
|
tools: EDITOR_TOOLS,
|
|
409
|
-
data: JSON.parse(record.params.
|
|
412
|
+
data: isSavedData ? JSON.parse(record.params[property.path]) : "",
|
|
410
413
|
async onChange(api, event) {
|
|
411
414
|
const data = await api.saver.save();
|
|
412
415
|
setJsonData(JSON.stringify(data));
|
|
@@ -421,8 +424,33 @@ var Editor = ({ property, record, onChangeAdmin, editorId }) => {
|
|
|
421
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 })));
|
|
422
425
|
};
|
|
423
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;
|
|
424
451
|
export {
|
|
425
452
|
CustomSlug_default as CustomSlug,
|
|
426
453
|
Editor_default as Editor,
|
|
454
|
+
EditorShow_default as EditorShow,
|
|
427
455
|
StringList_default as StringList
|
|
428
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.
|
|
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
|
+
};
|