@rulab/adminjs-components 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -3
- package/dist/components/ColorStatus/ColorStatusEdit.js +7 -3
- package/dist/components/ColorStatus/ColorStatusFeature.d.ts +1 -0
- package/dist/components/ColorStatus/ColorStatusFeature.js +8 -2
- package/dist/components/Editor/Editor.d.ts +7 -9
- package/dist/components/Editor/Editor.js +8 -5
- package/dist/components/Editor/EditorList.d.ts +4 -6
- package/dist/components/Editor/EditorList.js +2 -1
- package/dist/components/Editor/EditorShow.d.ts +4 -6
- package/dist/components/Editor/EditorShow.js +4 -1
- package/dist/components/Slug/SlugEdit.js +1 -1
- package/dist/components/Slug/SlugFeature.js +2 -2
- package/dist/components/Slug/SlugOptions.type.d.ts +1 -0
- package/dist/components/StringList/StringList.js +5 -4
- package/dist/components/StringList/StringListFeature.d.ts +1 -0
- package/dist/components/StringList/StringListFeature.js +2 -1
- package/dist/components/StringList/StringListShow.js +6 -4
- package/dist/components/Uuid/UuidEdit.d.ts +5 -0
- package/dist/components/Uuid/UuidEdit.js +34 -0
- package/dist/components/Uuid/UuidFeature.d.ts +4 -0
- package/dist/components/Uuid/UuidFeature.js +21 -0
- package/dist/components/Uuid/UuidOptions.type.d.ts +7 -0
- package/dist/components/Uuid/UuidOptions.type.js +1 -0
- package/dist/components/Uuid/styles.d.ts +4 -0
- package/dist/components/Uuid/styles.js +20 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/package.json +35 -16
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# adminjs-components
|
|
2
2
|
|
|
3
3
|
Prebuilt AdminJS components and features for common UI needs: colored status
|
|
4
|
-
badges, slug generation, Editor.js content, sortable string lists, tabs
|
|
5
|
-
and record preview.
|
|
4
|
+
badges, slug and UUID generation, Editor.js content, sortable string lists, tabs
|
|
5
|
+
layout, and record preview.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -49,6 +49,8 @@ You can also pass `componentLoader` into every feature instead of calling
|
|
|
49
49
|
### ColorStatus
|
|
50
50
|
|
|
51
51
|
Renders a colored badge in edit/list/show based on a list of available values.
|
|
52
|
+
By default (`nullable: false`) the first option is auto-selected in new records.
|
|
53
|
+
Set `nullable: true` to allow an empty value.
|
|
52
54
|
|
|
53
55
|
```ts
|
|
54
56
|
import { ColorStatusFeature } from "@rulab/adminjs-components";
|
|
@@ -56,6 +58,7 @@ import { ColorStatusFeature } from "@rulab/adminjs-components";
|
|
|
56
58
|
features: [
|
|
57
59
|
ColorStatusFeature({
|
|
58
60
|
key: "status",
|
|
61
|
+
nullable: false, // optional, default false
|
|
59
62
|
availableValues: [
|
|
60
63
|
{ value: "draft", label: "Draft", color: "#64748b" },
|
|
61
64
|
{ value: "review", label: "In review", color: "#f59e0b" },
|
|
@@ -68,6 +71,7 @@ features: [
|
|
|
68
71
|
### Slug
|
|
69
72
|
|
|
70
73
|
Generates a slug from another field and stores it in the target property.
|
|
74
|
+
Use `button` to override the generate button label in edit view.
|
|
71
75
|
|
|
72
76
|
```ts
|
|
73
77
|
import { SlugFeature } from "@rulab/adminjs-components";
|
|
@@ -76,6 +80,23 @@ features: [
|
|
|
76
80
|
SlugFeature({
|
|
77
81
|
key: "slug",
|
|
78
82
|
source: "title",
|
|
83
|
+
button: "Create slug", // optional
|
|
84
|
+
}),
|
|
85
|
+
]
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### UUID
|
|
89
|
+
|
|
90
|
+
Adds a UUID field with a "Generate UUID" button in edit view.
|
|
91
|
+
Use `button` to override the generate button label.
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
import { UuidFeature } from "@rulab/adminjs-components";
|
|
95
|
+
|
|
96
|
+
features: [
|
|
97
|
+
UuidFeature({
|
|
98
|
+
key: "uuid",
|
|
99
|
+
button: "Generate ID", // optional
|
|
79
100
|
}),
|
|
80
101
|
]
|
|
81
102
|
```
|
|
@@ -105,6 +126,7 @@ features: [
|
|
|
105
126
|
### StringList
|
|
106
127
|
|
|
107
128
|
Sortable list stored as a single string (comma-separated by default).
|
|
129
|
+
Use `separator` to override the delimiter used for storing and rendering values.
|
|
108
130
|
|
|
109
131
|
```ts
|
|
110
132
|
import { StringListFeature } from "@rulab/adminjs-components";
|
|
@@ -112,6 +134,7 @@ import { StringListFeature } from "@rulab/adminjs-components";
|
|
|
112
134
|
features: [
|
|
113
135
|
StringListFeature({
|
|
114
136
|
key: "facts",
|
|
137
|
+
separator: "|", // optional, default "|"
|
|
115
138
|
}),
|
|
116
139
|
]
|
|
117
140
|
```
|
|
@@ -120,13 +143,14 @@ features: [
|
|
|
120
143
|
|
|
121
144
|
Groups edit/show fields into tabs based on property `props.tab` or
|
|
122
145
|
`custom.tab`. Fields without a tab go to a common group.
|
|
146
|
+
`commonTabLabel` is optional and defaults to `"Common"`.
|
|
123
147
|
|
|
124
148
|
```ts
|
|
125
149
|
import { TabsFeature } from "@rulab/adminjs-components";
|
|
126
150
|
|
|
127
151
|
features: [
|
|
128
152
|
TabsFeature({
|
|
129
|
-
commonTabLabel: "Common"
|
|
153
|
+
commonTabLabel: "General", // optional, default "Common"
|
|
130
154
|
}),
|
|
131
155
|
]
|
|
132
156
|
|
|
@@ -43,8 +43,12 @@ const colorStyles = {
|
|
|
43
43
|
};
|
|
44
44
|
export const ColorStatusEdit = ({ property, record, onChange, }) => {
|
|
45
45
|
const availableValues = property.availableValues;
|
|
46
|
-
const
|
|
47
|
-
const
|
|
46
|
+
const nullable = Boolean(property.custom?.nullable);
|
|
47
|
+
const isNewRecord = !record.id;
|
|
48
|
+
const currentValue = record.params[property.path];
|
|
49
|
+
const currentOption = availableValues.find((item) => item.value === currentValue);
|
|
50
|
+
const initialOption = currentOption ?? (!nullable && isNewRecord ? availableValues[0] : null);
|
|
51
|
+
const [selectOption, setCurrentOption] = useState(initialOption);
|
|
48
52
|
const handleSelectChange = (option) => {
|
|
49
53
|
setCurrentOption(option);
|
|
50
54
|
};
|
|
@@ -53,6 +57,6 @@ export const ColorStatusEdit = ({ property, record, onChange, }) => {
|
|
|
53
57
|
}, [selectOption]);
|
|
54
58
|
return (React.createElement(ColorStatusWrapper, null,
|
|
55
59
|
React.createElement(Label, null, property.label ?? property.path),
|
|
56
|
-
React.createElement(Select, { className: "basic-single", classNamePrefix: "select",
|
|
60
|
+
React.createElement(Select, { className: "basic-single", classNamePrefix: "select", value: selectOption, onChange: handleSelectChange, isClearable: nullable, name: "color", options: availableValues, styles: colorStyles })));
|
|
57
61
|
};
|
|
58
62
|
export default ColorStatusEdit;
|
|
@@ -4,6 +4,7 @@ type ColorStatusOptions = {
|
|
|
4
4
|
componentLoader?: ComponentLoader;
|
|
5
5
|
key: string;
|
|
6
6
|
availableValues?: AvailableValueType[];
|
|
7
|
+
nullable?: boolean;
|
|
7
8
|
};
|
|
8
9
|
export declare const ColorStatusFeature: (config: ColorStatusOptions) => FeatureType;
|
|
9
10
|
export default ColorStatusFeature;
|
|
@@ -2,7 +2,10 @@ import { buildFeature } from "adminjs";
|
|
|
2
2
|
import { bundleComponent } from "../../utils/bundle-component.js";
|
|
3
3
|
const COMPONENT_NAME = "ColorStatus";
|
|
4
4
|
export const ColorStatusFeature = (config) => {
|
|
5
|
-
const { componentLoader, key, availableValues = [] } = config;
|
|
5
|
+
const { componentLoader, key, availableValues = [], nullable = false } = config;
|
|
6
|
+
const values = nullable
|
|
7
|
+
? [{ value: null, label: "", color: "#ffffff" }, ...availableValues]
|
|
8
|
+
: availableValues;
|
|
6
9
|
const editComponent = bundleComponent(componentLoader, COMPONENT_NAME, "ColorStatusEdit.js");
|
|
7
10
|
const listComponent = bundleComponent(componentLoader, COMPONENT_NAME, "ColorStatusList.js");
|
|
8
11
|
const showComponent = bundleComponent(componentLoader, COMPONENT_NAME, "ColorStatusShow.js");
|
|
@@ -10,7 +13,10 @@ export const ColorStatusFeature = (config) => {
|
|
|
10
13
|
properties: {
|
|
11
14
|
[key]: {
|
|
12
15
|
isVisible: { filter: true, show: true, edit: true, list: true },
|
|
13
|
-
availableValues,
|
|
16
|
+
availableValues: values,
|
|
17
|
+
custom: {
|
|
18
|
+
nullable,
|
|
19
|
+
},
|
|
14
20
|
components: {
|
|
15
21
|
edit: editComponent,
|
|
16
22
|
list: listComponent,
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
import React from "react";
|
|
2
|
+
type EditorProps = {
|
|
2
3
|
property: any;
|
|
3
4
|
record: any;
|
|
4
5
|
resource: any;
|
|
5
|
-
onChange:
|
|
6
|
-
onChangeAdmin:
|
|
7
|
-
editorId
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
theme: import("styled-components").DefaultTheme | ((outerTheme?: import("styled-components").DefaultTheme | undefined) => import("styled-components").DefaultTheme);
|
|
11
|
-
}>;
|
|
6
|
+
onChange?: (path: string, value: string | undefined) => void;
|
|
7
|
+
onChangeAdmin?: (path: string, value: string | undefined) => void;
|
|
8
|
+
editorId?: string;
|
|
9
|
+
};
|
|
10
|
+
export declare const Editor: ({ property, record, resource, onChange, onChangeAdmin, editorId, }: EditorProps) => React.JSX.Element;
|
|
12
11
|
export default Editor;
|
|
13
|
-
import React from "react";
|
|
@@ -22,15 +22,15 @@ const getEditorData = (record, property) => {
|
|
|
22
22
|
try {
|
|
23
23
|
return JSON.parse(raw);
|
|
24
24
|
}
|
|
25
|
-
catch
|
|
25
|
+
catch {
|
|
26
26
|
return "";
|
|
27
27
|
}
|
|
28
28
|
};
|
|
29
|
-
export const Editor = ({ property, record, resource, onChange, onChangeAdmin, editorId }) => {
|
|
29
|
+
export const Editor = ({ property, record, resource, onChange, onChangeAdmin, editorId, }) => {
|
|
30
30
|
const [jsonData, setJsonData] = useState();
|
|
31
31
|
const isSavedData = Boolean(record?.params?.[property.path]);
|
|
32
32
|
const holderId = editorId || property?.props?.editorId || `editor-${property.path}`;
|
|
33
|
-
const uploadAction = property?.props?.uploadAction;
|
|
33
|
+
const uploadAction = property?.custom?.uploadAction ?? property?.props?.uploadAction;
|
|
34
34
|
const resourceId = resource?.id;
|
|
35
35
|
const ref = useRef();
|
|
36
36
|
useEffect(() => {
|
|
@@ -78,7 +78,7 @@ export const Editor = ({ property, record, resource, onChange, onChangeAdmin, ed
|
|
|
78
78
|
holder: holderId,
|
|
79
79
|
tools,
|
|
80
80
|
data: isSavedData ? getEditorData(record, property) : "",
|
|
81
|
-
async onChange(api
|
|
81
|
+
async onChange(api) {
|
|
82
82
|
const data = await api.saver.save();
|
|
83
83
|
setJsonData(JSON.stringify(data));
|
|
84
84
|
},
|
|
@@ -91,6 +91,9 @@ export const Editor = ({ property, record, resource, onChange, onChangeAdmin, ed
|
|
|
91
91
|
ref?.current?.destroy?.();
|
|
92
92
|
};
|
|
93
93
|
}, []);
|
|
94
|
-
return (React.createElement(ThemeProvider, { theme: theme },
|
|
94
|
+
return (React.createElement(ThemeProvider, { theme: theme },
|
|
95
|
+
React.createElement(StyledLabel, null, property.label ?? property.path),
|
|
96
|
+
React.createElement(StyledEditorWrapper, null,
|
|
97
|
+
React.createElement(StyledEditor, { id: holderId }))));
|
|
95
98
|
};
|
|
96
99
|
export default Editor;
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import React from "react";
|
|
2
|
+
type EditorListProps = {
|
|
2
3
|
property: any;
|
|
3
4
|
record: any;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
theme: import("styled-components").DefaultTheme | ((outerTheme?: import("styled-components").DefaultTheme | undefined) => import("styled-components").DefaultTheme);
|
|
7
|
-
}>;
|
|
5
|
+
};
|
|
6
|
+
export declare const EditorList: ({ property, record }: EditorListProps) => React.JSX.Element;
|
|
8
7
|
export default EditorList;
|
|
9
|
-
import React from "react";
|
|
@@ -5,6 +5,7 @@ import { parseHtml } from "../../utils/parseHtml.js";
|
|
|
5
5
|
import { StyledEditorViewWrapper } from "./styles.js";
|
|
6
6
|
export const EditorList = ({ property, record }) => {
|
|
7
7
|
const htmlContent = parseHtml(record.params[property.path]);
|
|
8
|
-
return (React.createElement(ThemeProvider, { theme: theme },
|
|
8
|
+
return (React.createElement(ThemeProvider, { theme: theme },
|
|
9
|
+
React.createElement(StyledEditorViewWrapper, null, htmlContent && React.createElement("div", { dangerouslySetInnerHTML: { __html: htmlContent } }))));
|
|
9
10
|
};
|
|
10
11
|
export default EditorList;
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import React from "react";
|
|
2
|
+
type EditorShowProps = {
|
|
2
3
|
property: any;
|
|
3
4
|
record: any;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
theme: import("styled-components").DefaultTheme | ((outerTheme?: import("styled-components").DefaultTheme | undefined) => import("styled-components").DefaultTheme);
|
|
7
|
-
}>;
|
|
5
|
+
};
|
|
6
|
+
export declare const EditorShow: ({ property, record }: EditorShowProps) => React.JSX.Element;
|
|
8
7
|
export default EditorShow;
|
|
9
|
-
import React from "react";
|
|
@@ -5,6 +5,9 @@ import { parseHtml } from "../../utils/parseHtml.js";
|
|
|
5
5
|
import { StyledEditorShowWrapper, StyledShowLabel } from "./styles.js";
|
|
6
6
|
export const EditorShow = ({ property, record }) => {
|
|
7
7
|
const htmlContent = parseHtml(record.params[property.path]);
|
|
8
|
-
return (React.createElement(ThemeProvider, { theme: theme },
|
|
8
|
+
return (React.createElement(ThemeProvider, { theme: theme },
|
|
9
|
+
React.createElement(StyledEditorShowWrapper, null,
|
|
10
|
+
React.createElement(StyledShowLabel, null, property.label ?? property.path),
|
|
11
|
+
htmlContent && React.createElement("div", { dangerouslySetInnerHTML: { __html: htmlContent } }))));
|
|
9
12
|
};
|
|
10
13
|
export default EditorShow;
|
|
@@ -17,7 +17,7 @@ export const SlugEdit = ({ property, record, resource, onChange, }) => {
|
|
|
17
17
|
React.createElement(StyledLabel, { htmlFor: "customSlug" }, property.label ?? property.path),
|
|
18
18
|
React.createElement(StyledInputWrapper, null,
|
|
19
19
|
React.createElement(StyledCustomInput, { id: property.path, name: property.path, value: inputValue, onChange: handleInput }),
|
|
20
|
-
React.createElement(StyledGenerateButton, { variant: "outlined", onClick: generateSlug }, "Generate Slug"))));
|
|
20
|
+
React.createElement(StyledGenerateButton, { variant: "outlined", onClick: generateSlug }, custom.button ?? "Generate Slug"))));
|
|
21
21
|
function handleInput(e) {
|
|
22
22
|
setInputValue(e.target.value);
|
|
23
23
|
}
|
|
@@ -2,7 +2,7 @@ import { buildFeature } from "adminjs";
|
|
|
2
2
|
import { bundleComponent } from "../../utils/bundle-component.js";
|
|
3
3
|
const COMPONENT_NAME = 'Slug';
|
|
4
4
|
export const SlugFeature = (config) => {
|
|
5
|
-
const { componentLoader, source, key } = config;
|
|
5
|
+
const { componentLoader, source, key, button } = config;
|
|
6
6
|
const editComponent = bundleComponent(componentLoader, COMPONENT_NAME, 'SlugEdit.js');
|
|
7
7
|
return buildFeature({
|
|
8
8
|
properties: {
|
|
@@ -11,7 +11,7 @@ export const SlugFeature = (config) => {
|
|
|
11
11
|
components: {
|
|
12
12
|
edit: editComponent,
|
|
13
13
|
},
|
|
14
|
-
custom: { source, key }
|
|
14
|
+
custom: { source, key, button }
|
|
15
15
|
},
|
|
16
16
|
},
|
|
17
17
|
});
|
|
@@ -3,8 +3,9 @@ import React, { useEffect, useState, } from "react";
|
|
|
3
3
|
import { ThemeProvider } from "styled-components";
|
|
4
4
|
import { StyledCustomInput, StyledInputWrapper, StyledLabel, StyledListWrapper, StyledWrapper, } from "./styles.js";
|
|
5
5
|
import { SortableList } from "./SortableList/SortableList.js";
|
|
6
|
-
|
|
7
|
-
export const StringList = ({ record, onChange, property, stringListSeparator =
|
|
6
|
+
const DEFAULT_SEPARATOR = "|";
|
|
7
|
+
export const StringList = ({ record, onChange, property, stringListSeparator = DEFAULT_SEPARATOR, }) => {
|
|
8
|
+
const separatorValue = property.props?.stringListSeparator ?? stringListSeparator;
|
|
8
9
|
const stringListValue = record.params?.[property.path] ?? property.props.value ?? "";
|
|
9
10
|
const initialList = stringListValue
|
|
10
11
|
? prepareDataForList(stringListValue)
|
|
@@ -45,10 +46,10 @@ export const StringList = ({ record, onChange, property, stringListSeparator = s
|
|
|
45
46
|
setList(newData);
|
|
46
47
|
}
|
|
47
48
|
function prepareDataForDatabase(list) {
|
|
48
|
-
return list.map(({ value }) => value).join(
|
|
49
|
+
return list.map(({ value }) => value).join(separatorValue);
|
|
49
50
|
}
|
|
50
51
|
function prepareDataForList(str) {
|
|
51
|
-
return str.split(
|
|
52
|
+
return str.split(separatorValue).map((item) => createListObject(item));
|
|
52
53
|
}
|
|
53
54
|
function createListObject(value) {
|
|
54
55
|
return {
|
|
@@ -2,6 +2,7 @@ import { ComponentLoader, FeatureType } from "adminjs";
|
|
|
2
2
|
type StringListOptions = {
|
|
3
3
|
componentLoader?: ComponentLoader;
|
|
4
4
|
key: string;
|
|
5
|
+
separator?: string;
|
|
5
6
|
};
|
|
6
7
|
export declare const StringListFeature: (config: StringListOptions) => FeatureType;
|
|
7
8
|
export default StringListFeature;
|
|
@@ -2,13 +2,14 @@ import { buildFeature } from "adminjs";
|
|
|
2
2
|
import { bundleComponent } from "../../utils/bundle-component.js";
|
|
3
3
|
const COMPONENT_NAME = "StringList";
|
|
4
4
|
export const StringListFeature = (config) => {
|
|
5
|
-
const { componentLoader, key } = config;
|
|
5
|
+
const { componentLoader, key, separator } = config;
|
|
6
6
|
const editComponent = bundleComponent(componentLoader, COMPONENT_NAME, "StringList.js");
|
|
7
7
|
const showComponent = bundleComponent(componentLoader, COMPONENT_NAME, "StringListShow.js");
|
|
8
8
|
return buildFeature({
|
|
9
9
|
properties: {
|
|
10
10
|
[key]: {
|
|
11
11
|
isVisible: { filter: true, show: true, edit: true, list: true },
|
|
12
|
+
props: separator ? { stringListSeparator: separator } : undefined,
|
|
12
13
|
components: {
|
|
13
14
|
edit: editComponent,
|
|
14
15
|
show: showComponent,
|
|
@@ -2,13 +2,15 @@ import React from "react";
|
|
|
2
2
|
import { ThemeProvider } from "styled-components";
|
|
3
3
|
import { theme } from "@adminjs/design-system";
|
|
4
4
|
import { StyledShowLabel, StyledShowWrapper, StyledListItem } from "./styles.js";
|
|
5
|
-
|
|
6
|
-
export const StringListShow = ({ property, record, stringListSeparator =
|
|
5
|
+
const DEFAULT_SEPARATOR = "|";
|
|
6
|
+
export const StringListShow = ({ property, record, stringListSeparator = DEFAULT_SEPARATOR, }) => {
|
|
7
|
+
const separatorValue = property.props?.stringListSeparator ?? stringListSeparator;
|
|
8
|
+
const value = record.params[property.path];
|
|
7
9
|
return (React.createElement(ThemeProvider, { theme: theme },
|
|
8
10
|
React.createElement(StyledShowWrapper, null,
|
|
9
11
|
React.createElement(StyledShowLabel, null, property.label ?? property.path),
|
|
10
|
-
|
|
11
|
-
.split(
|
|
12
|
+
value && (React.createElement("ul", null, value
|
|
13
|
+
.split(separatorValue)
|
|
12
14
|
.map((item, index) => (React.createElement(StyledListItem, { key: index }, `- ${item}`))))))));
|
|
13
15
|
};
|
|
14
16
|
export default StringListShow;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
|
+
import { ThemeProvider } from "styled-components";
|
|
3
|
+
import { theme } from "@adminjs/design-system";
|
|
4
|
+
import { StyledCustomInput, StyledGenerateButton, StyledInputWrapper, StyledLabel, } from "./styles.js";
|
|
5
|
+
const generateUuidV4 = () => {
|
|
6
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
7
|
+
return crypto.randomUUID();
|
|
8
|
+
}
|
|
9
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (char) => {
|
|
10
|
+
const random = (Math.random() * 16) | 0;
|
|
11
|
+
const value = char === "x" ? random : (random & 0x3) | 0x8;
|
|
12
|
+
return value.toString(16);
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
export const UuidEdit = ({ property, record, onChange, }) => {
|
|
16
|
+
const { custom } = property;
|
|
17
|
+
const [inputValue, setInputValue] = useState(record.params[property.path] ?? "");
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
onChange(property.path, inputValue);
|
|
20
|
+
}, [inputValue]);
|
|
21
|
+
return (React.createElement(ThemeProvider, { theme: theme },
|
|
22
|
+
React.createElement(StyledLabel, { htmlFor: "customUuid" }, property.label ?? property.path),
|
|
23
|
+
React.createElement(StyledInputWrapper, null,
|
|
24
|
+
React.createElement(StyledCustomInput, { id: property.path, name: property.path, value: inputValue, onChange: handleInput }),
|
|
25
|
+
React.createElement(StyledGenerateButton, { variant: "outlined", onClick: generateUuid }, custom?.button ?? "Generate UUID"))));
|
|
26
|
+
function handleInput(e) {
|
|
27
|
+
setInputValue(e.target.value);
|
|
28
|
+
}
|
|
29
|
+
function generateUuid(e) {
|
|
30
|
+
e.preventDefault();
|
|
31
|
+
setInputValue(generateUuidV4());
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
export default UuidEdit;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { buildFeature } from "adminjs";
|
|
2
|
+
import { bundleComponent } from "../../utils/bundle-component.js";
|
|
3
|
+
const COMPONENT_NAME = "Uuid";
|
|
4
|
+
export const UuidFeature = (config) => {
|
|
5
|
+
const { componentLoader, key, button } = config;
|
|
6
|
+
const editComponent = bundleComponent(componentLoader, COMPONENT_NAME, "UuidEdit.js");
|
|
7
|
+
return buildFeature({
|
|
8
|
+
properties: {
|
|
9
|
+
[key]: {
|
|
10
|
+
isVisible: { filter: true, show: true, edit: true, list: true },
|
|
11
|
+
custom: {
|
|
12
|
+
button,
|
|
13
|
+
},
|
|
14
|
+
components: {
|
|
15
|
+
edit: editComponent,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
export default UuidFeature;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// @ts-ignore
|
|
2
|
+
import { styled } from "@adminjs/design-system/styled-components";
|
|
3
|
+
// @ts-ignore
|
|
4
|
+
import { Box, Button, 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
|
+
`;
|
|
16
|
+
export const StyledLabel = styled.div `
|
|
17
|
+
font-size: 12px;
|
|
18
|
+
margin-bottom: 8px;
|
|
19
|
+
text-transform: capitalize;
|
|
20
|
+
`;
|
|
@@ -13,3 +13,4 @@ export { StringListFeature } from "./StringList/StringListFeature.js";
|
|
|
13
13
|
export { SlugFeature } from "./Slug/SlugFeature.js";
|
|
14
14
|
export { TabsFeature } from "./Tabs/TabsFeature.js";
|
|
15
15
|
export { PreviewFeature } from "./Preview/PreviewFeature.js";
|
|
16
|
+
export { UuidFeature } from "./Uuid/UuidFeature.js";
|
package/dist/components/index.js
CHANGED
|
@@ -13,3 +13,4 @@ export { StringListFeature } from "./StringList/StringListFeature.js";
|
|
|
13
13
|
export { SlugFeature } from "./Slug/SlugFeature.js";
|
|
14
14
|
export { TabsFeature } from "./Tabs/TabsFeature.js";
|
|
15
15
|
export { PreviewFeature } from "./Preview/PreviewFeature.js";
|
|
16
|
+
export { UuidFeature } from "./Uuid/UuidFeature.js";
|
package/package.json
CHANGED
|
@@ -1,35 +1,55 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulab/adminjs-components",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Prebuilt AdminJS features for common UI needs.",
|
|
4
5
|
"main": "dist/index.js",
|
|
5
|
-
"module": "dist/index.mjs",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"private": false,
|
|
8
8
|
"type": "module",
|
|
9
|
+
"license": "MIT",
|
|
9
10
|
"keywords": [
|
|
10
|
-
"adminjs"
|
|
11
|
+
"adminjs",
|
|
12
|
+
"components",
|
|
13
|
+
"react",
|
|
14
|
+
"editorjs"
|
|
11
15
|
],
|
|
16
|
+
"homepage": "https://github.com/rulab/adminjs-components#readme",
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://github.com/rulab/adminjs-components/issues"
|
|
19
|
+
},
|
|
12
20
|
"repository": {
|
|
13
21
|
"url": "git+https://github.com/rulab/adminjs-components.git"
|
|
14
22
|
},
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public",
|
|
25
|
+
"registry": "https://registry.npmjs.org/"
|
|
26
|
+
},
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"import": "./dist/index.js",
|
|
31
|
+
"default": "./dist/index.js"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"sideEffects": false,
|
|
15
35
|
"scripts": {
|
|
16
|
-
"build": "tsc
|
|
17
|
-
"
|
|
18
|
-
"
|
|
36
|
+
"build": "tsc",
|
|
37
|
+
"lint": "tsc",
|
|
38
|
+
"prepublishOnly": "pnpm run build"
|
|
19
39
|
},
|
|
20
40
|
"dependencies": {
|
|
21
41
|
"@dnd-kit/core": "^6.1.0",
|
|
22
42
|
"@dnd-kit/sortable": "^8.0.0",
|
|
23
|
-
"@editorjs/editorjs": "2.30.2",
|
|
24
|
-
"@editorjs/header": "
|
|
25
|
-
"@editorjs/image": "
|
|
26
|
-
"@editorjs/list": "
|
|
27
|
-
"@editorjs/paragraph": "
|
|
28
|
-
"@editorjs/quote": "
|
|
29
|
-
"@editorjs/table": "
|
|
43
|
+
"@editorjs/editorjs": "~2.30.2",
|
|
44
|
+
"@editorjs/header": "~2.8.7",
|
|
45
|
+
"@editorjs/image": "~2.9.2",
|
|
46
|
+
"@editorjs/list": "~1.9.0",
|
|
47
|
+
"@editorjs/paragraph": "~2.11.6",
|
|
48
|
+
"@editorjs/quote": "~2.7.2",
|
|
49
|
+
"@editorjs/table": "~2.4.1",
|
|
30
50
|
"chroma-js": "^3.0.0",
|
|
31
|
-
"editorjs-audio-player": "
|
|
32
|
-
"editorjs-html": "
|
|
51
|
+
"editorjs-audio-player": "~0.0.3",
|
|
52
|
+
"editorjs-html": "~3.4.3",
|
|
33
53
|
"react-select": "^5.8.0",
|
|
34
54
|
"slugify": "^1.6.6"
|
|
35
55
|
},
|
|
@@ -53,7 +73,6 @@
|
|
|
53
73
|
"@types/node": "^20.11.24",
|
|
54
74
|
"@types/react": "^18.2.61",
|
|
55
75
|
"react": "^18.2.0",
|
|
56
|
-
"tsup": "^8.1.0",
|
|
57
76
|
"styled-components": "^6.1.11",
|
|
58
77
|
"typescript": "^5.3.2"
|
|
59
78
|
},
|