@rulab/adminjs-components 0.0.3 → 0.0.5

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.
Files changed (43) hide show
  1. package/dist/bundle.js +8 -0
  2. package/dist/components/CustomSlug/CustomSlug.jsx +29 -0
  3. package/dist/components/CustomSlug/index.js +1 -0
  4. package/dist/components/CustomSlug/styles.js +15 -0
  5. package/dist/components/Editor/config.js +11 -0
  6. package/dist/components/Editor/index.js +1 -0
  7. package/dist/components/Editor/styles.js +64 -0
  8. package/dist/components/StringList/SortableList/SortableList.jsx +43 -0
  9. package/dist/components/StringList/SortableList/components/SortableItem/DragHandle.jsx +10 -0
  10. package/dist/components/StringList/SortableList/components/SortableItem/SortableItem.jsx +32 -0
  11. package/dist/components/StringList/SortableList/components/SortableItem/styles.js +20 -0
  12. package/dist/components/StringList/SortableList/components/SortableItem/types.js +1 -0
  13. package/dist/components/StringList/SortableList/components/index.js +2 -0
  14. package/dist/components/StringList/SortableList/index.js +1 -0
  15. package/dist/components/StringList/SortableList/styles.js +8 -0
  16. package/dist/components/StringList/StringList.jsx +67 -0
  17. package/dist/components/StringList/index.js +1 -0
  18. package/dist/components/StringList/styles.js +16 -0
  19. package/dist/components/index.js +3 -0
  20. package/dist/editorFeature.js +16 -0
  21. package/dist/index.cjs +91 -26
  22. package/dist/index.d.cts +16 -3
  23. package/dist/index.d.mts +8 -0
  24. package/dist/index.d.ts +16 -3
  25. package/dist/index.js +83 -20
  26. package/dist/index.mjs +37 -0
  27. package/dist/utils/index.js +1 -0
  28. package/dist/utils/slugifyImport.js +3 -0
  29. package/dist/utils/slugifyTitle.js +10 -0
  30. package/package.json +2 -1
  31. package/src/components/CustomSlug/CustomSlug.tsx +4 -2
  32. package/src/components/Editor/Editor.jsx +2 -1
  33. package/src/components/Editor/EditorShow.jsx +22 -0
  34. package/src/components/Editor/index.ts +2 -1
  35. package/src/components/Editor/styles.ts +2 -0
  36. package/src/components/StringList/StringList.tsx +13 -3
  37. package/src/components/StringList/StringListShow.tsx +37 -0
  38. package/src/components/StringList/constants.ts +1 -0
  39. package/src/components/StringList/index.ts +2 -1
  40. package/src/components/StringList/styles.ts +17 -0
  41. package/src/components/index.ts +3 -1
  42. package/src/utils/parseHtml.ts +12 -0
  43. 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,11 @@
1
+ import Header from "@editorjs/header";
2
+ import Paragraph from "@editorjs/paragraph";
3
+ import List from "@editorjs/list";
4
+ export const EDITOR_TOOLS = {
5
+ paragraph: {
6
+ class: Paragraph,
7
+ inlineToolbar: true,
8
+ },
9
+ list: List,
10
+ header: Header,
11
+ };
@@ -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,2 @@
1
+ export { SortableItem } from './SortableItem/SortableItem.js';
2
+ export { DragHandle } from './SortableItem/DragHandle.js';
@@ -0,0 +1 @@
1
+ export { SortableList } from './SortableList.js';
@@ -0,0 +1,8 @@
1
+ import { styled } from '@adminjs/design-system/styled-components';
2
+ export const StyledListWrapper = styled.ul `
3
+ display: flex;
4
+ flex-direction: column;
5
+ gap: 12px;
6
+ padding: 0;
7
+ list-style: none;
8
+ `;
@@ -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,3 @@
1
+ export { default as CustomSlug } from "./CustomSlug/CustomSlug.js";
2
+ export { default as StringList } from "./StringList/StringList.js";
3
+ export { default as Editor } from "./Editor";
@@ -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,7 +32,9 @@ var src_exports = {};
32
32
  __export(src_exports, {
33
33
  CustomSlug: () => CustomSlug_default,
34
34
  Editor: () => Editor_default,
35
- StringList: () => StringList_default
35
+ EditorShow: () => EditorShow_default,
36
+ StringList: () => StringList_default,
37
+ StringListShow: () => StringListShow_default
36
38
  });
37
39
  module.exports = __toCommonJS(src_exports);
38
40
 
@@ -49,7 +51,7 @@ var slugifyImport_default = import_slugify.default;
49
51
  var slugifyTitle = (title) => {
50
52
  return slugifyImport_default(title, {
51
53
  replacement: "-",
52
- remove: void 0,
54
+ remove: /[*+~.()'"!:@]/g,
53
55
  lower: true,
54
56
  locale: "vi",
55
57
  trim: true
@@ -91,8 +93,10 @@ var CustomSlug = ({ property, record, onChange }) => {
91
93
  }
92
94
  function generateSlug(e) {
93
95
  e.preventDefault();
94
- const title = record.title;
95
- setInputValue(slugifyTitle(title));
96
+ const title = record.params.title;
97
+ if (title) {
98
+ setInputValue(slugifyTitle(title));
99
+ }
96
100
  }
97
101
  };
98
102
  var CustomSlug_default = CustomSlug;
@@ -108,6 +112,7 @@ var import_design_system3 = require("@adminjs/design-system");
108
112
  var StyledWrapper = (0, import_styled_components3.styled)(import_design_system3.Box)`
109
113
  display: flex;
110
114
  flex-direction: column;
115
+ margin-bottom: 45px;
111
116
  `;
112
117
  var StyledCustomInput2 = (0, import_styled_components3.styled)(import_design_system3.Input)`
113
118
  width: 100%;
@@ -119,6 +124,19 @@ var StyledInputWrapper2 = (0, import_styled_components3.styled)(import_design_sy
119
124
  var StyledListWrapper = (0, import_styled_components3.styled)(import_design_system3.Box)`
120
125
  margin-bottom: 15px;
121
126
  `;
127
+ var StringListShowLabel = import_styled_components3.styled.div`
128
+ font-size: 12px;
129
+ margin-bottom: 8px;
130
+ text-transform: capitalize;
131
+ line-height: 16px;
132
+ color: rgb(137, 138, 154);
133
+ `;
134
+ var StringListShowWrapper = (0, import_styled_components3.styled)(import_design_system3.Box)`
135
+ margin-bottom: 35px;
136
+ `;
137
+ var ListItem = import_styled_components3.styled.li`
138
+ margin-bottom: 5px;
139
+ `;
122
140
 
123
141
  // src/components/StringList/SortableList/SortableList.tsx
124
142
  var import_react4 = __toESM(require("react"), 1);
@@ -258,8 +276,16 @@ function SortableList({
258
276
  }
259
277
  SortableList.Item = SortableItem;
260
278
 
279
+ // src/constants.ts
280
+ var separator = "|";
281
+
261
282
  // src/components/StringList/StringList.tsx
262
- var StringList = ({ record, onChange, property }) => {
283
+ var StringList = ({
284
+ record,
285
+ onChange,
286
+ property,
287
+ stringListSeparator = separator
288
+ }) => {
263
289
  const stringListValue = record.params?.[property.path] ?? property.props.value ?? "";
264
290
  const initialList = stringListValue ? prepareDataForList(stringListValue) : [];
265
291
  const [inputValue, setInputValue] = (0, import_react5.useState)("");
@@ -314,10 +340,10 @@ var StringList = ({ record, onChange, property }) => {
314
340
  setList(newData);
315
341
  }
316
342
  function prepareDataForDatabase(list2) {
317
- return list2.map(({ value }) => value).join("|");
343
+ return list2.map(({ value }) => value).join(stringListSeparator);
318
344
  }
319
345
  function prepareDataForList(str) {
320
- return str.split("|").map((item) => createListObject(item));
346
+ return str.split(stringListSeparator).map((item) => createListObject(item));
321
347
  }
322
348
  function createListObject(value) {
323
349
  return {
@@ -328,24 +354,40 @@ var StringList = ({ record, onChange, property }) => {
328
354
  };
329
355
  var StringList_default = StringList;
330
356
 
331
- // src/components/Editor/Editor.jsx
357
+ // src/components/StringList/StringListShow.tsx
332
358
  var import_react6 = __toESM(require("react"), 1);
333
- var import_styled_components8 = require("styled-components");
359
+ var import_styled_components7 = require("styled-components");
360
+ var import_design_system6 = require("@adminjs/design-system");
361
+ var StringListShow = ({
362
+ property,
363
+ record,
364
+ stringListSeparator = separator
365
+ }) => {
366
+ console.log(stringListSeparator, "stringListSeparator");
367
+ return /* @__PURE__ */ import_react6.default.createElement(import_styled_components7.ThemeProvider, { theme: import_design_system6.theme }, /* @__PURE__ */ import_react6.default.createElement(StringListShowWrapper, null, /* @__PURE__ */ import_react6.default.createElement(StringListShowLabel, null, property.name), record.params.facts && /* @__PURE__ */ import_react6.default.createElement("ul", null, record.params.facts.split(stringListSeparator).map((item, index) => /* @__PURE__ */ import_react6.default.createElement(ListItem, { key: index }, `- ${item}`)))));
368
+ };
369
+ var StringListShow_default = StringListShow;
370
+
371
+ // src/components/Editor/Editor.jsx
372
+ var import_react7 = __toESM(require("react"), 1);
373
+ var import_styled_components9 = require("styled-components");
334
374
  var import_editorjs = __toESM(require("@editorjs/editorjs"), 1);
335
- var import_design_system7 = require("@adminjs/design-system");
375
+ var import_design_system8 = require("@adminjs/design-system");
336
376
 
337
377
  // src/components/Editor/styles.ts
338
- var import_design_system6 = require("@adminjs/design-system");
339
- var import_styled_components7 = require("@adminjs/design-system/styled-components");
340
- var Label3 = import_styled_components7.styled.div`
378
+ var import_design_system7 = require("@adminjs/design-system");
379
+ var import_styled_components8 = require("@adminjs/design-system/styled-components");
380
+ var Label3 = import_styled_components8.styled.div`
341
381
  font-size: 12px;
342
382
  margin-bottom: 8px;
383
+ color: rgb(137, 138, 154);
343
384
  `;
344
- var EditorWrapper = (0, import_styled_components7.styled)(import_design_system6.Box)`
385
+ var EditorWrapper = (0, import_styled_components8.styled)(import_design_system7.Box)`
345
386
  padding: 12px;
387
+ margin-bottom: 24px;
346
388
  border: 1px solid rgb(187, 195, 203);
347
389
  `;
348
- var StyledEditor = import_styled_components7.styled.div`
390
+ var StyledEditor = import_styled_components8.styled.div`
349
391
  .cdx-block,
350
392
  .ce-header {
351
393
  padding-left: 58px;
@@ -415,21 +457,18 @@ var EDITOR_TOOLS = {
415
457
 
416
458
  // src/components/Editor/Editor.jsx
417
459
  var Editor = ({ property, record, onChangeAdmin, editorId }) => {
418
- const [jsonData, setJsonData] = (0, import_react6.useState)();
419
- console.log(
420
- record.params[property.path],
421
- "record.params[property.path].path"
422
- );
423
- const ref = (0, import_react6.useRef)();
424
- (0, import_react6.useEffect)(() => {
460
+ const [jsonData, setJsonData] = (0, import_react7.useState)();
461
+ const isSavedData = Boolean(record.params[property.path]);
462
+ const ref = (0, import_react7.useRef)();
463
+ (0, import_react7.useEffect)(() => {
425
464
  onChangeAdmin(property.path, jsonData);
426
465
  }, [jsonData]);
427
- (0, import_react6.useEffect)(() => {
466
+ (0, import_react7.useEffect)(() => {
428
467
  if (!ref.current) {
429
468
  const editor = new import_editorjs.default({
430
469
  holder: editorId,
431
470
  tools: EDITOR_TOOLS,
432
- data: JSON.parse(record.params[property.path]),
471
+ data: isSavedData ? JSON.parse(record.params[property.path]) : "",
433
472
  async onChange(api, event) {
434
473
  const data = await api.saver.save();
435
474
  setJsonData(JSON.stringify(data));
@@ -441,12 +480,38 @@ var Editor = ({ property, record, onChangeAdmin, editorId }) => {
441
480
  ref?.current?.destroy?.();
442
481
  };
443
482
  }, []);
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 })));
483
+ return /* @__PURE__ */ import_react7.default.createElement(import_styled_components9.ThemeProvider, { theme: import_design_system8.theme }, /* @__PURE__ */ import_react7.default.createElement(Label3, null, "Text"), /* @__PURE__ */ import_react7.default.createElement(EditorWrapper, null, /* @__PURE__ */ import_react7.default.createElement(StyledEditor, { id: editorId })));
445
484
  };
446
485
  var Editor_default = Editor;
486
+
487
+ // src/components/Editor/EditorShow.jsx
488
+ var import_react8 = __toESM(require("react"), 1);
489
+ var import_styled_components10 = require("styled-components");
490
+ var import_design_system9 = require("@adminjs/design-system");
491
+
492
+ // src/utils/parseHtml.ts
493
+ var import_editorjs_html = __toESM(require("editorjs-html"), 1);
494
+ var parseHtml = (jsonData) => {
495
+ const edjsParser = (0, import_editorjs_html.default)();
496
+ try {
497
+ const data = edjsParser.parse(JSON.parse(String(jsonData)));
498
+ return String(data).replace(/>,</g, "><");
499
+ } catch (e) {
500
+ return;
501
+ }
502
+ };
503
+
504
+ // src/components/Editor/EditorShow.jsx
505
+ var EditorShow = ({ property, record }) => {
506
+ const htmlContent = parseHtml(record.params[property.path]);
507
+ return /* @__PURE__ */ import_react8.default.createElement(import_styled_components10.ThemeProvider, { theme: import_design_system9.theme }, /* @__PURE__ */ import_react8.default.createElement(Label3, null, "Content"), htmlContent && /* @__PURE__ */ import_react8.default.createElement("div", { dangerouslySetInnerHTML: { __html: String(htmlContent) } }));
508
+ };
509
+ var EditorShow_default = EditorShow;
447
510
  // Annotate the CommonJS export names for ESM import in node:
448
511
  0 && (module.exports = {
449
512
  CustomSlug,
450
513
  Editor,
451
- StringList
514
+ EditorShow,
515
+ StringList,
516
+ StringListShow
452
517
  });
package/dist/index.d.cts CHANGED
@@ -1,11 +1,19 @@
1
1
  import React, { FC } from 'react';
2
- import { EditPropertyProps } from 'adminjs';
2
+ import { EditPropertyProps, ShowPropertyProps } from 'adminjs';
3
3
 
4
4
  type CustomSlugTypes = Omit<EditPropertyProps, "where" | "resource">;
5
5
  declare const CustomSlug: FC<CustomSlugTypes>;
6
6
 
7
7
  type StringListTypes = Omit<EditPropertyProps, "where" | "resource">;
8
- declare const StringList: FC<StringListTypes>;
8
+ interface StringListShowPropsType$1 extends StringListTypes {
9
+ stringListSeparator?: string;
10
+ }
11
+ declare const StringList: FC<StringListShowPropsType$1>;
12
+
13
+ interface StringListShowPropsType extends ShowPropertyProps {
14
+ stringListSeparator?: string;
15
+ }
16
+ declare const StringListShow: FC<StringListShowPropsType>;
9
17
 
10
18
  declare function Editor({ property, record, onChangeAdmin, editorId }: {
11
19
  property: any;
@@ -14,4 +22,9 @@ declare function Editor({ property, record, onChangeAdmin, editorId }: {
14
22
  editorId: any;
15
23
  }): React.JSX.Element;
16
24
 
17
- export { CustomSlug, Editor, StringList };
25
+ declare function EditorShow({ property, record }: {
26
+ property: any;
27
+ record: any;
28
+ }): React.JSX.Element;
29
+
30
+ export { CustomSlug, Editor, EditorShow, StringList, StringListShow };
@@ -0,0 +1,8 @@
1
+ import { FeatureType, ComponentLoader } from 'adminjs';
2
+
3
+ type EditorOptions = {
4
+ componentLoader: ComponentLoader;
5
+ };
6
+ declare const editorFeature: (options: EditorOptions) => FeatureType;
7
+
8
+ export { editorFeature as default, editorFeature };
package/dist/index.d.ts CHANGED
@@ -1,11 +1,19 @@
1
1
  import React, { FC } from 'react';
2
- import { EditPropertyProps } from 'adminjs';
2
+ import { EditPropertyProps, ShowPropertyProps } from 'adminjs';
3
3
 
4
4
  type CustomSlugTypes = Omit<EditPropertyProps, "where" | "resource">;
5
5
  declare const CustomSlug: FC<CustomSlugTypes>;
6
6
 
7
7
  type StringListTypes = Omit<EditPropertyProps, "where" | "resource">;
8
- declare const StringList: FC<StringListTypes>;
8
+ interface StringListShowPropsType$1 extends StringListTypes {
9
+ stringListSeparator?: string;
10
+ }
11
+ declare const StringList: FC<StringListShowPropsType$1>;
12
+
13
+ interface StringListShowPropsType extends ShowPropertyProps {
14
+ stringListSeparator?: string;
15
+ }
16
+ declare const StringListShow: FC<StringListShowPropsType>;
9
17
 
10
18
  declare function Editor({ property, record, onChangeAdmin, editorId }: {
11
19
  property: any;
@@ -14,4 +22,9 @@ declare function Editor({ property, record, onChangeAdmin, editorId }: {
14
22
  editorId: any;
15
23
  }): React.JSX.Element;
16
24
 
17
- export { CustomSlug, Editor, StringList };
25
+ declare function EditorShow({ property, record }: {
26
+ property: any;
27
+ record: any;
28
+ }): React.JSX.Element;
29
+
30
+ export { CustomSlug, Editor, EditorShow, StringList, StringListShow };
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: void 0,
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
- setInputValue(slugifyTitle(title));
59
+ const title = record.params.title;
60
+ if (title) {
61
+ setInputValue(slugifyTitle(title));
62
+ }
61
63
  }
62
64
  };
63
65
  var CustomSlug_default = CustomSlug;
@@ -76,6 +78,7 @@ import { Box as Box2, Input as Input2 } from "@adminjs/design-system";
76
78
  var StyledWrapper = styled2(Box2)`
77
79
  display: flex;
78
80
  flex-direction: column;
81
+ margin-bottom: 45px;
79
82
  `;
80
83
  var StyledCustomInput2 = styled2(Input2)`
81
84
  width: 100%;
@@ -87,6 +90,19 @@ var StyledInputWrapper2 = styled2(Box2)`
87
90
  var StyledListWrapper = styled2(Box2)`
88
91
  margin-bottom: 15px;
89
92
  `;
93
+ var StringListShowLabel = styled2.div`
94
+ font-size: 12px;
95
+ margin-bottom: 8px;
96
+ text-transform: capitalize;
97
+ line-height: 16px;
98
+ color: rgb(137, 138, 154);
99
+ `;
100
+ var StringListShowWrapper = styled2(Box2)`
101
+ margin-bottom: 35px;
102
+ `;
103
+ var ListItem = styled2.li`
104
+ margin-bottom: 5px;
105
+ `;
90
106
 
91
107
  // src/components/StringList/SortableList/SortableList.tsx
92
108
  import React4, { Fragment, useMemo as useMemo2, useState as useState2 } from "react";
@@ -239,8 +255,16 @@ function SortableList({
239
255
  }
240
256
  SortableList.Item = SortableItem;
241
257
 
258
+ // src/constants.ts
259
+ var separator = "|";
260
+
242
261
  // src/components/StringList/StringList.tsx
243
- var StringList = ({ record, onChange, property }) => {
262
+ var StringList = ({
263
+ record,
264
+ onChange,
265
+ property,
266
+ stringListSeparator = separator
267
+ }) => {
244
268
  const stringListValue = record.params?.[property.path] ?? property.props.value ?? "";
245
269
  const initialList = stringListValue ? prepareDataForList(stringListValue) : [];
246
270
  const [inputValue, setInputValue] = useState3("");
@@ -295,10 +319,10 @@ var StringList = ({ record, onChange, property }) => {
295
319
  setList(newData);
296
320
  }
297
321
  function prepareDataForDatabase(list2) {
298
- return list2.map(({ value }) => value).join("|");
322
+ return list2.map(({ value }) => value).join(stringListSeparator);
299
323
  }
300
324
  function prepareDataForList(str) {
301
- return str.split("|").map((item) => createListObject(item));
325
+ return str.split(stringListSeparator).map((item) => createListObject(item));
302
326
  }
303
327
  function createListObject(value) {
304
328
  return {
@@ -309,11 +333,25 @@ var StringList = ({ record, onChange, property }) => {
309
333
  };
310
334
  var StringList_default = StringList;
311
335
 
312
- // src/components/Editor/Editor.jsx
313
- import React6, { memo, useState as useState4, useEffect as useEffect3, useRef } from "react";
336
+ // src/components/StringList/StringListShow.tsx
337
+ import React6 from "react";
314
338
  import { ThemeProvider as ThemeProvider3 } from "styled-components";
315
- import EditorJS from "@editorjs/editorjs";
316
339
  import { theme as theme3 } from "@adminjs/design-system";
340
+ var StringListShow = ({
341
+ property,
342
+ record,
343
+ stringListSeparator = separator
344
+ }) => {
345
+ console.log(stringListSeparator, "stringListSeparator");
346
+ return /* @__PURE__ */ React6.createElement(ThemeProvider3, { theme: theme3 }, /* @__PURE__ */ React6.createElement(StringListShowWrapper, null, /* @__PURE__ */ React6.createElement(StringListShowLabel, null, property.name), record.params.facts && /* @__PURE__ */ React6.createElement("ul", null, record.params.facts.split(stringListSeparator).map((item, index) => /* @__PURE__ */ React6.createElement(ListItem, { key: index }, `- ${item}`)))));
347
+ };
348
+ var StringListShow_default = StringListShow;
349
+
350
+ // src/components/Editor/Editor.jsx
351
+ import React7, { memo as memo2, useState as useState5, useEffect as useEffect4, useRef as useRef2 } from "react";
352
+ import { ThemeProvider as ThemeProvider4 } from "styled-components";
353
+ import EditorJS from "@editorjs/editorjs";
354
+ import { theme as theme4 } from "@adminjs/design-system";
317
355
 
318
356
  // src/components/Editor/styles.ts
319
357
  import { Box as Box3 } from "@adminjs/design-system";
@@ -321,9 +359,11 @@ import { styled as styled5 } from "@adminjs/design-system/styled-components";
321
359
  var Label3 = styled5.div`
322
360
  font-size: 12px;
323
361
  margin-bottom: 8px;
362
+ color: rgb(137, 138, 154);
324
363
  `;
325
364
  var EditorWrapper = styled5(Box3)`
326
365
  padding: 12px;
366
+ margin-bottom: 24px;
327
367
  border: 1px solid rgb(187, 195, 203);
328
368
  `;
329
369
  var StyledEditor = styled5.div`
@@ -396,21 +436,18 @@ var EDITOR_TOOLS = {
396
436
 
397
437
  // src/components/Editor/Editor.jsx
398
438
  var Editor = ({ property, record, onChangeAdmin, editorId }) => {
399
- const [jsonData, setJsonData] = useState4();
400
- console.log(
401
- record.params[property.path],
402
- "record.params[property.path].path"
403
- );
404
- const ref = useRef();
405
- useEffect3(() => {
439
+ const [jsonData, setJsonData] = useState5();
440
+ const isSavedData = Boolean(record.params[property.path]);
441
+ const ref = useRef2();
442
+ useEffect4(() => {
406
443
  onChangeAdmin(property.path, jsonData);
407
444
  }, [jsonData]);
408
- useEffect3(() => {
445
+ useEffect4(() => {
409
446
  if (!ref.current) {
410
447
  const editor = new EditorJS({
411
448
  holder: editorId,
412
449
  tools: EDITOR_TOOLS,
413
- data: JSON.parse(record.params[property.path]),
450
+ data: isSavedData ? JSON.parse(record.params[property.path]) : "",
414
451
  async onChange(api, event) {
415
452
  const data = await api.saver.save();
416
453
  setJsonData(JSON.stringify(data));
@@ -422,11 +459,37 @@ var Editor = ({ property, record, onChangeAdmin, editorId }) => {
422
459
  ref?.current?.destroy?.();
423
460
  };
424
461
  }, []);
425
- return /* @__PURE__ */ React6.createElement(ThemeProvider3, { theme: theme3 }, /* @__PURE__ */ React6.createElement(Label3, null, "Text"), /* @__PURE__ */ React6.createElement(EditorWrapper, null, /* @__PURE__ */ React6.createElement(StyledEditor, { id: editorId })));
462
+ return /* @__PURE__ */ React7.createElement(ThemeProvider4, { theme: theme4 }, /* @__PURE__ */ React7.createElement(Label3, null, "Text"), /* @__PURE__ */ React7.createElement(EditorWrapper, null, /* @__PURE__ */ React7.createElement(StyledEditor, { id: editorId })));
426
463
  };
427
464
  var Editor_default = Editor;
465
+
466
+ // src/components/Editor/EditorShow.jsx
467
+ import React8, { memo as memo3, useState as useState6, useEffect as useEffect5, useRef as useRef3 } from "react";
468
+ import { ThemeProvider as ThemeProvider5 } from "styled-components";
469
+ import { theme as theme5 } from "@adminjs/design-system";
470
+
471
+ // src/utils/parseHtml.ts
472
+ import edjsHTML from "editorjs-html";
473
+ var parseHtml = (jsonData) => {
474
+ const edjsParser = edjsHTML();
475
+ try {
476
+ const data = edjsParser.parse(JSON.parse(String(jsonData)));
477
+ return String(data).replace(/>,</g, "><");
478
+ } catch (e) {
479
+ return;
480
+ }
481
+ };
482
+
483
+ // src/components/Editor/EditorShow.jsx
484
+ var EditorShow = ({ property, record }) => {
485
+ const htmlContent = parseHtml(record.params[property.path]);
486
+ return /* @__PURE__ */ React8.createElement(ThemeProvider5, { theme: theme5 }, /* @__PURE__ */ React8.createElement(Label3, null, "Content"), htmlContent && /* @__PURE__ */ React8.createElement("div", { dangerouslySetInnerHTML: { __html: String(htmlContent) } }));
487
+ };
488
+ var EditorShow_default = EditorShow;
428
489
  export {
429
490
  CustomSlug_default as CustomSlug,
430
491
  Editor_default as Editor,
431
- StringList_default as StringList
492
+ EditorShow_default as EditorShow,
493
+ StringList_default as StringList,
494
+ StringListShow_default as StringListShow
432
495
  };
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";
@@ -0,0 +1,3 @@
1
+ // This is a fix of typescript module import error
2
+ import * as slugify from "slugify";
3
+ export default slugify;
@@ -0,0 +1,10 @@
1
+ import * as slugify from "slugify";
2
+ export const slugifyTitle = (title) => {
3
+ return slugify.default(title, {
4
+ replacement: "-",
5
+ remove: undefined,
6
+ lower: true,
7
+ locale: "vi",
8
+ trim: true,
9
+ });
10
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rulab/adminjs-components",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
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
- setInputValue(slugifyTitle(title));
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 { default } from "./Editor.jsx";
1
+ export * from "./Editor.jsx";
2
+ export * from "./EditorShow.jsx";
@@ -4,10 +4,12 @@ import { styled } from "@adminjs/design-system/styled-components";
4
4
  export const Label = styled.div`
5
5
  font-size: 12px;
6
6
  margin-bottom: 8px;
7
+ color: rgb(137, 138, 154);
7
8
  `;
8
9
 
9
10
  export const EditorWrapper = styled(Box)`
10
11
  padding: 12px;
12
+ margin-bottom: 24px;
11
13
  border: 1px solid rgb(187, 195, 203);
12
14
  `;
13
15
 
@@ -18,6 +18,7 @@ import {
18
18
  } from "./styles.js";
19
19
 
20
20
  import { SortableList } from "./SortableList/SortableList.js";
21
+ import { separator } from "./constants.js";
21
22
 
22
23
  type ListDataTypes = {
23
24
  id: string;
@@ -26,7 +27,16 @@ type ListDataTypes = {
26
27
 
27
28
  type StringListTypes = Omit<EditPropertyProps, "where" | "resource">;
28
29
 
29
- const StringList: FC<StringListTypes> = ({ record, onChange, property }) => {
30
+ interface StringListShowPropsType extends StringListTypes {
31
+ stringListSeparator?: string;
32
+ }
33
+
34
+ const StringList: FC<StringListShowPropsType> = ({
35
+ record,
36
+ onChange,
37
+ property,
38
+ stringListSeparator = separator,
39
+ }) => {
30
40
  const stringListValue =
31
41
  record.params?.[property.path] ?? property.props.value ?? "";
32
42
 
@@ -107,11 +117,11 @@ const StringList: FC<StringListTypes> = ({ record, onChange, property }) => {
107
117
  }
108
118
 
109
119
  function prepareDataForDatabase(list: ListDataTypes[]) {
110
- return list.map(({ value }) => value).join("|");
120
+ return list.map(({ value }) => value).join(stringListSeparator);
111
121
  }
112
122
 
113
123
  function prepareDataForList(str: string) {
114
- return str.split("|").map((item) => createListObject(item));
124
+ return str.split(stringListSeparator).map((item) => createListObject(item));
115
125
  }
116
126
 
117
127
  function createListObject(value: string) {
@@ -0,0 +1,37 @@
1
+ import React, { memo, useState, useEffect, useRef, FC } from "react";
2
+ import { ShowPropertyProps } from "adminjs";
3
+
4
+ import { ThemeProvider } from "styled-components";
5
+ import { theme } from "@adminjs/design-system";
6
+
7
+ import { StringListShowLabel, StringListShowWrapper, ListItem } from "./styles";
8
+ import { separator } from "./constants";
9
+
10
+ interface StringListShowPropsType extends ShowPropertyProps {
11
+ stringListSeparator?: string;
12
+ }
13
+
14
+ const StringListShow: FC<StringListShowPropsType> = ({
15
+ property,
16
+ record,
17
+ stringListSeparator = separator,
18
+ }) => {
19
+ return (
20
+ <ThemeProvider theme={theme}>
21
+ <StringListShowWrapper>
22
+ <StringListShowLabel>{property.name}</StringListShowLabel>
23
+ {record.params.facts && (
24
+ <ul>
25
+ {record.params.facts
26
+ .split(stringListSeparator)
27
+ .map((item: string, index: number) => (
28
+ <ListItem key={index}>{`- ${item}`}</ListItem>
29
+ ))}
30
+ </ul>
31
+ )}
32
+ </StringListShowWrapper>
33
+ </ThemeProvider>
34
+ );
35
+ };
36
+
37
+ export default StringListShow;
@@ -0,0 +1 @@
1
+ export const separator = "|";
@@ -1 +1,2 @@
1
- export { default } from "./StringList.js";
1
+ export * from "./StringList.js";
2
+ export * from "./StringListShow.js";
@@ -4,6 +4,7 @@ import { Box, Input } from "@adminjs/design-system";
4
4
  export const StyledWrapper = styled(Box)`
5
5
  display: flex;
6
6
  flex-direction: column;
7
+ margin-bottom: 45px;
7
8
  `;
8
9
 
9
10
  export const StyledCustomInput = styled(Input)`
@@ -18,3 +19,19 @@ export const StyledInputWrapper = styled(Box)`
18
19
  export const StyledListWrapper = styled(Box)`
19
20
  margin-bottom: 15px;
20
21
  `;
22
+
23
+ export const StringListShowLabel = styled.div`
24
+ font-size: 12px;
25
+ margin-bottom: 8px;
26
+ text-transform: capitalize;
27
+ line-height: 16px;
28
+ color: rgb(137, 138, 154);
29
+ `;
30
+
31
+ export const StringListShowWrapper = styled(Box)`
32
+ margin-bottom: 35px;
33
+ `;
34
+
35
+ export const ListItem = styled.li`
36
+ margin-bottom: 5px;
37
+ `;
@@ -1,3 +1,5 @@
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 StringListShow } from "./StringList/StringListShow.js";
4
+ export { default as Editor } from "./Editor/Editor.jsx";
5
+ 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
+ };
@@ -3,7 +3,7 @@ import slugify from "./slugifyImport.js";
3
3
  export const slugifyTitle = (title: string) => {
4
4
  return slugify(title, {
5
5
  replacement: "-",
6
- remove: undefined,
6
+ remove: /[*+~.()'"!:@]/g,
7
7
  lower: true,
8
8
  locale: "vi",
9
9
  trim: true,