@rulab/adminjs-components 0.1.0-alpha.8 → 0.1.0-beta.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.
Files changed (159) hide show
  1. package/dist/components/ColorStatus/ColorStatusEdit.d.ts +2 -2
  2. package/dist/components/ColorStatus/ColorStatusEdit.js +3 -3
  3. package/dist/components/ColorStatus/ColorStatusFeature.d.ts +9 -0
  4. package/dist/components/ColorStatus/ColorStatusFeature.js +23 -0
  5. package/dist/components/ColorStatus/ColorStatusList.d.ts +1 -1
  6. package/dist/components/ColorStatus/ColorStatusList.js +4 -2
  7. package/dist/components/ColorStatus/ColorStatusShow.d.ts +1 -1
  8. package/dist/components/ColorStatus/ColorStatusShow.js +5 -3
  9. package/dist/components/ColorStatus/index.d.ts +4 -3
  10. package/dist/components/ColorStatus/index.js +4 -3
  11. package/dist/components/ColorStatus/styles.js +2 -1
  12. package/dist/components/Editor/Editor.d.ts +4 -2
  13. package/dist/components/Editor/Editor.js +79 -16
  14. package/dist/components/Editor/EditorFeature.d.ts +10 -0
  15. package/dist/components/Editor/EditorFeature.js +82 -0
  16. package/dist/components/Editor/EditorList.d.ts +2 -2
  17. package/dist/components/Editor/EditorList.js +1 -1
  18. package/dist/components/Editor/EditorShow.d.ts +2 -2
  19. package/dist/components/Editor/EditorShow.js +2 -2
  20. package/dist/components/Editor/index.d.ts +4 -3
  21. package/dist/components/Editor/index.js +4 -3
  22. package/dist/components/FeatureTabs/FeatureTabsEdit.d.ts +4 -0
  23. package/dist/components/FeatureTabs/FeatureTabsEdit.js +105 -0
  24. package/dist/components/FeatureTabs/FeatureTabsFeature.d.ts +8 -0
  25. package/dist/components/FeatureTabs/FeatureTabsFeature.js +28 -0
  26. package/dist/components/FeatureTabs/FeatureTabsShow.d.ts +4 -0
  27. package/dist/components/FeatureTabs/FeatureTabsShow.js +61 -0
  28. package/dist/components/FeatureTabs/index.d.ts +4 -0
  29. package/dist/components/FeatureTabs/index.js +4 -0
  30. package/dist/components/Preview/PreviewAction.d.ts +4 -0
  31. package/dist/components/Preview/PreviewAction.js +22 -0
  32. package/dist/components/Preview/PreviewFeature.d.ts +9 -0
  33. package/dist/components/Preview/PreviewFeature.js +31 -0
  34. package/dist/components/Preview/index.d.ts +2 -0
  35. package/dist/components/Preview/index.js +2 -0
  36. package/dist/components/Slug/SlugEdit.d.ts +1 -1
  37. package/dist/components/Slug/SlugEdit.js +9 -3
  38. package/dist/components/Slug/SlugFeature.d.ts +3 -6
  39. package/dist/components/Slug/SlugFeature.js +12 -14
  40. package/dist/components/Slug/SlugOptions.type.d.ts +7 -0
  41. package/dist/components/StringList/StringList.d.ts +1 -1
  42. package/dist/components/StringList/StringList.js +4 -4
  43. package/dist/components/StringList/StringListFeature.d.ts +7 -0
  44. package/dist/components/StringList/StringListFeature.js +20 -0
  45. package/dist/components/StringList/StringListShow.d.ts +1 -1
  46. package/dist/components/StringList/StringListShow.js +2 -2
  47. package/dist/components/StringList/index.d.ts +3 -2
  48. package/dist/components/StringList/index.js +3 -2
  49. package/dist/components/StringList/styles.js +2 -1
  50. package/dist/components/Tabs/TabsEdit.d.ts +4 -0
  51. package/dist/components/Tabs/TabsEdit.js +103 -0
  52. package/dist/components/Tabs/TabsFeature.d.ts +7 -0
  53. package/dist/components/Tabs/TabsFeature.js +26 -0
  54. package/dist/components/Tabs/TabsShow.d.ts +4 -0
  55. package/dist/components/Tabs/TabsShow.js +61 -0
  56. package/dist/components/Tabs/index.d.ts +3 -0
  57. package/dist/components/Tabs/index.js +3 -0
  58. package/dist/components/index.d.ts +15 -7
  59. package/dist/components/index.js +15 -10
  60. package/dist/index.d.ts +1 -0
  61. package/dist/index.js +1 -0
  62. package/dist/types/upload-provider.d.ts +13 -0
  63. package/dist/utils/bundle-component.d.ts +1 -1
  64. package/dist/utils/bundle-component.js +5 -8
  65. package/dist/utils/component-loader.d.ts +3 -0
  66. package/dist/utils/component-loader.js +10 -0
  67. package/dist/utils/index.d.ts +1 -0
  68. package/dist/utils/index.js +1 -0
  69. package/package.json +12 -11
  70. package/src/components/ColorStatus/ColorStatusEdit.d.ts +0 -5
  71. package/src/components/ColorStatus/ColorStatusEdit.js +0 -58
  72. package/src/components/ColorStatus/ColorStatusEdit.tsx +0 -94
  73. package/src/components/ColorStatus/ColorStatusList.d.ts +0 -4
  74. package/src/components/ColorStatus/ColorStatusList.js +0 -7
  75. package/src/components/ColorStatus/ColorStatusList.tsx +0 -20
  76. package/src/components/ColorStatus/ColorStatusShow.d.ts +0 -4
  77. package/src/components/ColorStatus/ColorStatusShow.js +0 -9
  78. package/src/components/ColorStatus/ColorStatusShow.tsx +0 -23
  79. package/src/components/ColorStatus/index.d.ts +0 -3
  80. package/src/components/ColorStatus/index.js +0 -3
  81. package/src/components/ColorStatus/index.ts +0 -3
  82. package/src/components/ColorStatus/styles.d.ts +0 -5
  83. package/src/components/ColorStatus/styles.js +0 -25
  84. package/src/components/ColorStatus/styles.ts +0 -30
  85. package/src/components/ColorStatus/types.d.ts +0 -5
  86. package/src/components/ColorStatus/types.ts +0 -5
  87. package/src/components/Editor/Editor.d.ts +0 -8
  88. package/src/components/Editor/Editor.js +0 -36
  89. package/src/components/Editor/Editor.jsx +0 -49
  90. package/src/components/Editor/EditorList.d.ts +0 -6
  91. package/src/components/Editor/EditorList.js +0 -11
  92. package/src/components/Editor/EditorList.jsx +0 -22
  93. package/src/components/Editor/EditorShow.d.ts +0 -6
  94. package/src/components/Editor/EditorShow.js +0 -13
  95. package/src/components/Editor/EditorShow.jsx +0 -24
  96. package/src/components/Editor/config.d.ts +0 -29
  97. package/src/components/Editor/config.js +0 -34
  98. package/src/components/Editor/config.ts +0 -35
  99. package/src/components/Editor/index.d.ts +0 -3
  100. package/src/components/Editor/index.js +0 -3
  101. package/src/components/Editor/index.ts +0 -3
  102. package/src/components/Editor/styles.d.ts +0 -6
  103. package/src/components/Editor/styles.js +0 -145
  104. package/src/components/Editor/styles.ts +0 -151
  105. package/src/components/Slug/SlugEdit.d.ts +0 -5
  106. package/src/components/Slug/SlugEdit.js +0 -27
  107. package/src/components/Slug/SlugEdit.tsx +0 -68
  108. package/src/components/Slug/SlugFeature.d.ts +0 -7
  109. package/src/components/Slug/SlugFeature.js +0 -21
  110. package/src/components/Slug/SlugFeature.ts +0 -30
  111. package/src/components/Slug/index.d.ts +0 -1
  112. package/src/components/Slug/index.js +0 -1
  113. package/src/components/Slug/index.ts +0 -1
  114. package/src/components/Slug/styles.d.ts +0 -4
  115. package/src/components/Slug/styles.js +0 -20
  116. package/src/components/Slug/styles.ts +0 -24
  117. package/src/components/StringList/SortableList/SortableList.d.ts +0 -18
  118. package/src/components/StringList/SortableList/SortableList.js +0 -37
  119. package/src/components/StringList/SortableList/SortableList.tsx +0 -98
  120. package/src/components/StringList/SortableList/components/SortableItem/DragHandle.d.ts +0 -7
  121. package/src/components/StringList/SortableList/components/SortableItem/DragHandle.js +0 -8
  122. package/src/components/StringList/SortableList/components/SortableItem/DragHandle.tsx +0 -20
  123. package/src/components/StringList/SortableList/components/SortableItem/SortableItem.d.ts +0 -8
  124. package/src/components/StringList/SortableList/components/SortableItem/SortableItem.js +0 -28
  125. package/src/components/StringList/SortableList/components/SortableItem/SortableItem.tsx +0 -59
  126. package/src/components/StringList/SortableList/components/SortableItem/styles.d.ts +0 -2
  127. package/src/components/StringList/SortableList/components/SortableItem/styles.js +0 -20
  128. package/src/components/StringList/SortableList/components/SortableItem/styles.ts +0 -22
  129. package/src/components/StringList/SortableList/components/SortableItem/types.d.ts +0 -6
  130. package/src/components/StringList/SortableList/components/SortableItem/types.ts +0 -7
  131. package/src/components/StringList/SortableList/components/index.d.ts +0 -2
  132. package/src/components/StringList/SortableList/components/index.js +0 -2
  133. package/src/components/StringList/SortableList/components/index.ts +0 -2
  134. package/src/components/StringList/SortableList/index.d.ts +0 -1
  135. package/src/components/StringList/SortableList/index.js +0 -1
  136. package/src/components/StringList/SortableList/index.ts +0 -1
  137. package/src/components/StringList/SortableList/styles.d.ts +0 -1
  138. package/src/components/StringList/SortableList/styles.js +0 -8
  139. package/src/components/StringList/SortableList/styles.ts +0 -9
  140. package/src/components/StringList/StringList.d.ts +0 -8
  141. package/src/components/StringList/StringList.js +0 -60
  142. package/src/components/StringList/StringList.tsx +0 -136
  143. package/src/components/StringList/StringListShow.d.ts +0 -7
  144. package/src/components/StringList/StringListShow.js +0 -14
  145. package/src/components/StringList/StringListShow.tsx +0 -37
  146. package/src/components/StringList/constants.d.ts +0 -1
  147. package/src/components/StringList/constants.js +0 -1
  148. package/src/components/StringList/constants.ts +0 -1
  149. package/src/components/StringList/index.d.ts +0 -2
  150. package/src/components/StringList/index.js +0 -2
  151. package/src/components/StringList/index.ts +0 -2
  152. package/src/components/StringList/styles.d.ts +0 -8
  153. package/src/components/StringList/styles.js +0 -33
  154. package/src/components/StringList/styles.ts +0 -41
  155. package/src/components/index.d.ts +0 -7
  156. package/src/components/index.js +0 -10
  157. package/src/components/index.ts +0 -10
  158. /package/{src/components/ColorStatus/types.js → dist/components/Slug/SlugOptions.type.js} +0 -0
  159. /package/{src/components/StringList/SortableList/components/SortableItem/types.js → dist/types/upload-provider.js} +0 -0
@@ -1,5 +1,5 @@
1
1
  import { FC } from "react";
2
2
  import { EditPropertyProps } from "adminjs";
3
3
  type ColorStatusTypes = Omit<EditPropertyProps, "where" | "resource">;
4
- declare const ColorStatus: FC<ColorStatusTypes>;
5
- export default ColorStatus;
4
+ export declare const ColorStatusEdit: FC<ColorStatusTypes>;
5
+ export default ColorStatusEdit;
@@ -41,7 +41,7 @@ const colorStyles = {
41
41
  placeholder: (styles) => ({ ...styles, ...dot("#ccc") }),
42
42
  singleValue: (styles, { data }) => ({ ...styles, ...dot(data.color) }),
43
43
  };
44
- const ColorStatus = ({ property, record, onChange }) => {
44
+ export const ColorStatusEdit = ({ property, record, onChange, }) => {
45
45
  const availableValues = property.availableValues;
46
46
  const currentOption = availableValues.find((item) => item.value === record.params[property.path]);
47
47
  const [selectOption, setCurrentOption] = useState(currentOption);
@@ -52,7 +52,7 @@ const ColorStatus = ({ property, record, onChange }) => {
52
52
  onChange(property.path, selectOption?.value);
53
53
  }, [selectOption]);
54
54
  return (React.createElement(ColorStatusWrapper, null,
55
- React.createElement(Label, null, property.path),
55
+ React.createElement(Label, null, property.label ?? property.path),
56
56
  React.createElement(Select, { className: "basic-single", classNamePrefix: "select", defaultValue: selectOption ?? availableValues[0], onChange: handleSelectChange, isClearable: true, name: "color", options: availableValues, styles: colorStyles })));
57
57
  };
58
- export default ColorStatus;
58
+ export default ColorStatusEdit;
@@ -0,0 +1,9 @@
1
+ import { ComponentLoader, FeatureType } from "adminjs";
2
+ import type { AvailableValueType } from "./types.js";
3
+ type ColorStatusOptions = {
4
+ componentLoader?: ComponentLoader;
5
+ key: string;
6
+ availableValues?: AvailableValueType[];
7
+ };
8
+ export declare const ColorStatusFeature: (config: ColorStatusOptions) => FeatureType;
9
+ export default ColorStatusFeature;
@@ -0,0 +1,23 @@
1
+ import { buildFeature } from "adminjs";
2
+ import { bundleComponent } from "../../utils/bundle-component.js";
3
+ const COMPONENT_NAME = "ColorStatus";
4
+ export const ColorStatusFeature = (config) => {
5
+ const { componentLoader, key, availableValues = [] } = config;
6
+ const editComponent = bundleComponent(componentLoader, COMPONENT_NAME, "ColorStatusEdit.js");
7
+ const listComponent = bundleComponent(componentLoader, COMPONENT_NAME, "ColorStatusList.js");
8
+ const showComponent = bundleComponent(componentLoader, COMPONENT_NAME, "ColorStatusShow.js");
9
+ return buildFeature({
10
+ properties: {
11
+ [key]: {
12
+ isVisible: { filter: true, show: true, edit: true, list: true },
13
+ availableValues,
14
+ components: {
15
+ edit: editComponent,
16
+ list: listComponent,
17
+ show: showComponent,
18
+ },
19
+ },
20
+ },
21
+ });
22
+ };
23
+ export default ColorStatusFeature;
@@ -1,4 +1,4 @@
1
1
  import { FC } from "react";
2
2
  import { ShowPropertyProps } from "adminjs";
3
- declare const ColorStatusList: FC<ShowPropertyProps>;
3
+ export declare const ColorStatusList: FC<ShowPropertyProps>;
4
4
  export default ColorStatusList;
@@ -1,7 +1,9 @@
1
1
  import React from "react";
2
2
  import { ColorStatusBadge } from "./styles.js";
3
- const ColorStatusList = ({ property, record }) => {
3
+ export const ColorStatusList = ({ property, record }) => {
4
4
  const currentOption = property.availableValues?.find((item) => item.value === record.params[property.path]);
5
- return (React.createElement(ColorStatusBadge, { color: currentOption.color }, record.params[property.path]));
5
+ const currentValue = record.params[property.path];
6
+ const displayValue = currentOption?.label ?? currentValue;
7
+ return (React.createElement(ColorStatusBadge, { color: currentOption?.color }, displayValue));
6
8
  };
7
9
  export default ColorStatusList;
@@ -1,4 +1,4 @@
1
1
  import { FC } from "react";
2
2
  import { ShowPropertyProps } from "adminjs";
3
- declare const ColorStatusShow: FC<ShowPropertyProps>;
3
+ export declare const ColorStatusShow: FC<ShowPropertyProps>;
4
4
  export default ColorStatusShow;
@@ -1,9 +1,11 @@
1
1
  import React from "react";
2
2
  import { ColorStatusBadgeWrapper, ColorStatusBadge, ShowLabel } from "./styles.js";
3
- const ColorStatusShow = ({ property, record }) => {
3
+ export const ColorStatusShow = ({ property, record }) => {
4
4
  const currentOption = property.availableValues?.find((item) => item.value === record.params[property.path]);
5
+ const currentValue = record.params[property.path];
6
+ const displayValue = currentOption?.label ?? currentValue;
5
7
  return (React.createElement(ColorStatusBadgeWrapper, null,
6
- React.createElement(ShowLabel, null, property.path),
7
- React.createElement(ColorStatusBadge, { color: currentOption.color }, record.params[property.path])));
8
+ React.createElement(ShowLabel, null, property.label ?? property.path),
9
+ React.createElement(ColorStatusBadge, { color: currentOption?.color }, displayValue)));
8
10
  };
9
11
  export default ColorStatusShow;
@@ -1,3 +1,4 @@
1
- export * from "./ColorStatusEdit.js";
2
- export * from "./ColorStatusShow.js";
3
- export * from "./ColorStatusList.js";
1
+ export { ColorStatusEdit } from "./ColorStatusEdit.js";
2
+ export { ColorStatusShow } from "./ColorStatusShow.js";
3
+ export { ColorStatusList } from "./ColorStatusList.js";
4
+ export { ColorStatusFeature } from "./ColorStatusFeature.js";
@@ -1,3 +1,4 @@
1
- export * from "./ColorStatusEdit.js";
2
- export * from "./ColorStatusShow.js";
3
- export * from "./ColorStatusList.js";
1
+ export { ColorStatusEdit } from "./ColorStatusEdit.js";
2
+ export { ColorStatusShow } from "./ColorStatusShow.js";
3
+ export { ColorStatusList } from "./ColorStatusList.js";
4
+ export { ColorStatusFeature } from "./ColorStatusFeature.js";
@@ -1,10 +1,11 @@
1
1
  import { styled } from "@adminjs/design-system/styled-components";
2
2
  export const ColorStatusWrapper = styled.div `
3
- margin-bottom: 24px;
3
+ margin-bottom: 45px;
4
4
  `;
5
5
  export const Label = styled.div `
6
6
  font-size: 12px;
7
7
  margin-bottom: 8px;
8
+ text-transform: capitalize;
8
9
  `;
9
10
  export const ShowLabel = styled.div `
10
11
  font-size: 12px;
@@ -1,11 +1,13 @@
1
- export default Editor;
2
- declare function Editor({ property, record, onChangeAdmin, editorId }: {
1
+ export function Editor({ property, record, resource, onChange, onChangeAdmin, editorId }: {
3
2
  property: any;
4
3
  record: any;
4
+ resource: any;
5
+ onChange: any;
5
6
  onChangeAdmin: any;
6
7
  editorId: any;
7
8
  }): React.FunctionComponentElement<{
8
9
  children?: React.ReactNode;
9
10
  theme: import("styled-components").DefaultTheme | ((outerTheme?: import("styled-components").DefaultTheme | undefined) => import("styled-components").DefaultTheme);
10
11
  }>;
12
+ export default Editor;
11
13
  import React from "react";
@@ -1,33 +1,96 @@
1
- import React, { memo, useState, useEffect, useRef } from "react";
1
+ import React, { useState, useEffect, useRef } from "react";
2
2
  import { ThemeProvider } from "styled-components";
3
- import EditorJS from "@editorjs/editorjs";
4
3
  import { theme } from "@adminjs/design-system";
4
+ import { ApiClient } from "adminjs";
5
5
  import { StyledLabel, StyledEditor, StyledEditorWrapper } from "./styles.js";
6
6
  import { EDITOR_TOOLS } from "./config.js";
7
- const Editor = ({ property, record, onChangeAdmin, editorId }) => {
7
+ const readFileAsBase64 = (file) => new Promise((resolve, reject) => {
8
+ const reader = new FileReader();
9
+ reader.onload = () => {
10
+ const result = reader.result ?? "";
11
+ const base64 = String(result).split(",")[1] ?? "";
12
+ resolve(base64);
13
+ };
14
+ reader.onerror = reject;
15
+ reader.readAsDataURL(file);
16
+ });
17
+ const getEditorData = (record, property) => {
18
+ const raw = record?.params?.[property.path];
19
+ if (!raw) {
20
+ return "";
21
+ }
22
+ try {
23
+ return JSON.parse(raw);
24
+ }
25
+ catch (error) {
26
+ return "";
27
+ }
28
+ };
29
+ export const Editor = ({ property, record, resource, onChange, onChangeAdmin, editorId }) => {
8
30
  const [jsonData, setJsonData] = useState();
9
- const isSavedData = Boolean(record.params[property.path]);
31
+ const isSavedData = Boolean(record?.params?.[property.path]);
32
+ const holderId = editorId || property?.props?.editorId || `editor-${property.path}`;
33
+ const uploadAction = property?.props?.uploadAction;
34
+ const resourceId = resource?.id;
10
35
  const ref = useRef();
11
36
  useEffect(() => {
12
- onChangeAdmin(property.path, jsonData);
37
+ const changeHandler = onChange ?? onChangeAdmin;
38
+ if (changeHandler) {
39
+ changeHandler(property.path, jsonData);
40
+ }
13
41
  }, [jsonData]);
14
42
  useEffect(() => {
15
43
  if (!ref.current) {
16
- const editor = new EditorJS({
17
- holder: editorId,
18
- tools: EDITOR_TOOLS,
19
- data: isSavedData ? JSON.parse(record.params[property.path]) : "",
20
- async onChange(api, event) {
21
- const data = await api.saver.save();
22
- setJsonData(JSON.stringify(data));
23
- },
24
- });
25
- ref.current = editor;
44
+ const init = async () => {
45
+ const { default: EditorJS } = await import("@editorjs/editorjs");
46
+ const tools = { ...EDITOR_TOOLS };
47
+ if (uploadAction && resourceId) {
48
+ const { default: ImageTool } = await import("@editorjs/image");
49
+ const api = new ApiClient();
50
+ tools.image = {
51
+ class: ImageTool,
52
+ config: {
53
+ uploader: {
54
+ uploadByFile: async (file) => {
55
+ const base64 = await readFileAsBase64(file);
56
+ const response = await api.resourceAction({
57
+ resourceId,
58
+ actionName: uploadAction,
59
+ data: {
60
+ file: {
61
+ name: file.name,
62
+ type: file.type,
63
+ base64,
64
+ },
65
+ },
66
+ });
67
+ const url = response?.data?.data?.url;
68
+ if (!url) {
69
+ return { success: 0 };
70
+ }
71
+ return { success: 1, file: { url } };
72
+ },
73
+ },
74
+ },
75
+ };
76
+ }
77
+ const editor = new EditorJS({
78
+ holder: holderId,
79
+ tools,
80
+ data: isSavedData ? getEditorData(record, property) : "",
81
+ async onChange(api, event) {
82
+ const data = await api.saver.save();
83
+ setJsonData(JSON.stringify(data));
84
+ },
85
+ });
86
+ ref.current = editor;
87
+ };
88
+ void init();
26
89
  }
27
90
  return () => {
28
91
  ref?.current?.destroy?.();
29
92
  };
30
93
  }, []);
31
- return (React.createElement(ThemeProvider, { theme: theme }, React.createElement(StyledLabel, null, property.path), React.createElement(StyledEditorWrapper, null, React.createElement(StyledEditor, { id: editorId }))));
94
+ return (React.createElement(ThemeProvider, { theme: theme }, React.createElement(StyledLabel, null, property.label ?? property.path), React.createElement(StyledEditorWrapper, null, React.createElement(StyledEditor, { id: holderId }))));
32
95
  };
33
96
  export default Editor;
@@ -0,0 +1,10 @@
1
+ import { ComponentLoader, FeatureType } from "adminjs";
2
+ import type { BaseProvider } from "@adminjs/upload";
3
+ type EditorOptions = {
4
+ componentLoader?: ComponentLoader;
5
+ key: string;
6
+ uploadProvider?: BaseProvider;
7
+ uploadActionName?: string;
8
+ };
9
+ export declare const EditorFeature: (config: EditorOptions) => FeatureType;
10
+ export default EditorFeature;
@@ -0,0 +1,82 @@
1
+ import { buildFeature } from "adminjs";
2
+ import { Buffer } from "node:buffer";
3
+ import { promises as fs } from "node:fs";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import { bundleComponent } from "../../utils/bundle-component.js";
7
+ import { slugifyTitle } from "../../utils/slugifyTitle.js";
8
+ const COMPONENT_NAME = "Editor";
9
+ export const EditorFeature = (config) => {
10
+ const { componentLoader, key, uploadProvider } = config;
11
+ const uploadActionName = config.uploadActionName ?? "editorUpload";
12
+ const editComponent = bundleComponent(componentLoader, COMPONENT_NAME, "Editor.js");
13
+ const listComponent = bundleComponent(componentLoader, COMPONENT_NAME, "EditorList.js");
14
+ const showComponent = bundleComponent(componentLoader, COMPONENT_NAME, "EditorShow.js");
15
+ return buildFeature({
16
+ actions: uploadProvider
17
+ ? {
18
+ [uploadActionName]: {
19
+ actionType: "resource",
20
+ isVisible: false,
21
+ handler: async (request, _response, context) => {
22
+ const file = request?.payload?.file;
23
+ if (!file?.base64) {
24
+ return {
25
+ data: { error: "No file provided." },
26
+ notice: { message: "No file provided.", type: "error" },
27
+ };
28
+ }
29
+ const buffer = Buffer.from(file.base64, "base64");
30
+ const originalName = file.name ?? "upload";
31
+ const filename = slugifyFilename(originalName);
32
+ const key = `${Date.now()}-${filename}`;
33
+ const tempPath = join(tmpdir(), `${Date.now()}-${filename}`);
34
+ const uploadedFile = {
35
+ name: filename,
36
+ type: file.type ?? "application/octet-stream",
37
+ size: buffer.length,
38
+ path: tempPath,
39
+ };
40
+ await fs.writeFile(tempPath, buffer);
41
+ try {
42
+ await uploadProvider.upload(uploadedFile, key, context);
43
+ }
44
+ finally {
45
+ await fs.unlink(tempPath).catch(() => undefined);
46
+ }
47
+ const baseUrl = uploadProvider.opts?.baseUrl;
48
+ const url = baseUrl
49
+ ? `${baseUrl.replace(/\/$/, "")}/${key}`
50
+ : await uploadProvider.path(key, uploadProvider.bucket, context);
51
+ if (!url) {
52
+ return {
53
+ data: { error: "Upload failed." },
54
+ notice: { message: "Upload failed.", type: "error" },
55
+ };
56
+ }
57
+ return { data: { url } };
58
+ },
59
+ },
60
+ }
61
+ : undefined,
62
+ properties: {
63
+ [key]: {
64
+ isVisible: { filter: true, show: true, edit: true, list: true },
65
+ props: uploadProvider ? { uploadAction: uploadActionName } : undefined,
66
+ components: {
67
+ edit: editComponent,
68
+ list: listComponent,
69
+ show: showComponent,
70
+ },
71
+ },
72
+ },
73
+ });
74
+ };
75
+ const slugifyFilename = (name) => {
76
+ const lastDot = name.lastIndexOf(".");
77
+ const base = lastDot > 0 ? name.slice(0, lastDot) : name;
78
+ const ext = lastDot > 0 ? name.slice(lastDot) : "";
79
+ const slug = slugifyTitle(base) || "file";
80
+ return `${slug}${ext}`;
81
+ };
82
+ export default EditorFeature;
@@ -1,9 +1,9 @@
1
- export default EditorList;
2
- declare function EditorList({ property, record }: {
1
+ export function EditorList({ property, record }: {
3
2
  property: any;
4
3
  record: any;
5
4
  }): React.FunctionComponentElement<{
6
5
  children?: React.ReactNode;
7
6
  theme: import("styled-components").DefaultTheme | ((outerTheme?: import("styled-components").DefaultTheme | undefined) => import("styled-components").DefaultTheme);
8
7
  }>;
8
+ export default EditorList;
9
9
  import React from "react";
@@ -3,7 +3,7 @@ import { theme } from "@adminjs/design-system";
3
3
  import { ThemeProvider } from "styled-components";
4
4
  import { parseHtml } from "../../utils/parseHtml.js";
5
5
  import { StyledEditorViewWrapper } from "./styles.js";
6
- const EditorList = ({ property, record }) => {
6
+ export const EditorList = ({ property, record }) => {
7
7
  const htmlContent = parseHtml(record.params[property.path]);
8
8
  return (React.createElement(ThemeProvider, { theme: theme }, React.createElement(StyledEditorViewWrapper, null, htmlContent && (React.createElement("div", { dangerouslySetInnerHTML: { __html: htmlContent } })))));
9
9
  };
@@ -1,9 +1,9 @@
1
- export default EditorShow;
2
- declare function EditorShow({ property, record }: {
1
+ export function EditorShow({ property, record }: {
3
2
  property: any;
4
3
  record: any;
5
4
  }): React.FunctionComponentElement<{
6
5
  children?: React.ReactNode;
7
6
  theme: import("styled-components").DefaultTheme | ((outerTheme?: import("styled-components").DefaultTheme | undefined) => import("styled-components").DefaultTheme);
8
7
  }>;
8
+ export default EditorShow;
9
9
  import React from "react";
@@ -3,8 +3,8 @@ import { ThemeProvider } from "styled-components";
3
3
  import { theme } from "@adminjs/design-system";
4
4
  import { parseHtml } from "../../utils/parseHtml.js";
5
5
  import { StyledEditorShowWrapper, StyledShowLabel } from "./styles.js";
6
- const EditorShow = ({ property, record }) => {
6
+ export const EditorShow = ({ property, record }) => {
7
7
  const htmlContent = parseHtml(record.params[property.path]);
8
- return (React.createElement(ThemeProvider, { theme: theme }, React.createElement(StyledEditorShowWrapper, null, React.createElement(StyledShowLabel, null, property.path), htmlContent && (React.createElement("div", { dangerouslySetInnerHTML: { __html: htmlContent } })))));
8
+ return (React.createElement(ThemeProvider, { theme: theme }, React.createElement(StyledEditorShowWrapper, null, React.createElement(StyledShowLabel, null, property.label ?? property.path), htmlContent && (React.createElement("div", { dangerouslySetInnerHTML: { __html: htmlContent } })))));
9
9
  };
10
10
  export default EditorShow;
@@ -1,3 +1,4 @@
1
- export * from "./Editor.jsx";
2
- export * from "./EditorShow.jsx";
3
- export * from "./EditorList.jsx";
1
+ export { Editor } from "./Editor.js";
2
+ export { EditorShow } from "./EditorShow.js";
3
+ export { EditorList } from "./EditorList.js";
4
+ export { EditorFeature } from "./EditorFeature.js";
@@ -1,3 +1,4 @@
1
- export * from "./Editor.jsx";
2
- export * from "./EditorShow.jsx";
3
- export * from "./EditorList.jsx";
1
+ export { Editor } from "./Editor.js";
2
+ export { EditorShow } from "./EditorShow.js";
3
+ export { EditorList } from "./EditorList.js";
4
+ export { EditorFeature } from "./EditorFeature.js";
@@ -0,0 +1,4 @@
1
+ import { FC } from "react";
2
+ import { ActionProps } from "adminjs";
3
+ export declare const FeatureTabsEdit: FC<ActionProps>;
4
+ export default FeatureTabsEdit;
@@ -0,0 +1,105 @@
1
+ import { Box, Button, DrawerContent, DrawerFooter, Icon, Tab, Tabs } from "@adminjs/design-system";
2
+ import { styled } from "@adminjs/design-system/styled-components";
3
+ import React, { useEffect, useMemo, useState } from "react";
4
+ import { BasePropertyComponent, LayoutElementRenderer, useRecord, useTranslation, ActionHeader, } from "adminjs";
5
+ const StyledTabButton = styled.button `
6
+ background: none;
7
+ border: none;
8
+ padding: ${({ theme }) => `${theme.space.sm} ${theme.space.xl}`};
9
+ cursor: pointer;
10
+ border-bottom: 2px solid ${({ theme }) => theme.colors.border};
11
+ color: ${({ theme }) => theme.colors.grey60};
12
+ user-select: none;
13
+ ${({ theme }) => ({
14
+ fontFamily: theme.font,
15
+ fontSize: theme.fontSizes.md,
16
+ lineHeight: theme.lineHeights.lg,
17
+ })};
18
+ ${({ active, theme }) => active
19
+ ? `
20
+ border-color: ${theme.colors.primary100};
21
+ color: ${theme.colors.primary100};
22
+ `
23
+ : ""}
24
+ `;
25
+ const StyledTabsContent = styled.div `
26
+ padding-top: ${({ theme }) => theme.space.xl};
27
+ `;
28
+ const TabButton = ({ onClick, active, tabId, role, children }) => (React.createElement(StyledTabButton, { type: "button", onClick: onClick, "data-tab-id": tabId, role: role, active: active }, children));
29
+ const DEFAULT_COMMON_LABEL = "Common";
30
+ const buildTabId = (label) => `tab-${label.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-_]/g, "")}`;
31
+ const groupProperties = (properties, commonLabel) => {
32
+ const commonProps = [];
33
+ const tabs = new Map();
34
+ properties.forEach((property) => {
35
+ const tab = property?.props?.tab ?? property?.custom?.tab;
36
+ if (tab) {
37
+ if (!tabs.has(tab)) {
38
+ tabs.set(tab, []);
39
+ }
40
+ tabs.get(tab)?.push(property);
41
+ }
42
+ else {
43
+ commonProps.push(property);
44
+ }
45
+ });
46
+ const entries = [
47
+ { id: "common", label: commonLabel, properties: commonProps },
48
+ ];
49
+ tabs.forEach((props, label) => {
50
+ entries.push({
51
+ id: buildTabId(label),
52
+ label,
53
+ properties: props,
54
+ });
55
+ });
56
+ return entries;
57
+ };
58
+ export const FeatureTabsEdit = (props) => {
59
+ const { record: initialRecord, resource, action } = props;
60
+ const { record, handleChange, submit: handleSubmit, loading, setRecord, } = useRecord(initialRecord, resource.id);
61
+ const { translateButton } = useTranslation();
62
+ useEffect(() => {
63
+ if (initialRecord) {
64
+ setRecord(initialRecord);
65
+ }
66
+ }, [initialRecord]);
67
+ const submit = (event) => {
68
+ event.preventDefault();
69
+ handleSubmit().then((response) => {
70
+ if (response.data.redirectUrl) {
71
+ window.location.assign(response.data.redirectUrl);
72
+ }
73
+ });
74
+ return false;
75
+ };
76
+ const formTag = undefined;
77
+ const footerTag = undefined;
78
+ const commonLabel = resource?.options?.properties?.__featureTabsCommonLabel?.custom?.value ??
79
+ DEFAULT_COMMON_LABEL;
80
+ const tabs = useMemo(() => groupProperties(resource.editProperties, commonLabel), [resource.editProperties, commonLabel]);
81
+ const [currentTab, setCurrentTab] = useState(() => {
82
+ const commonHasProps = Boolean(tabs[0]?.properties?.length);
83
+ return commonHasProps ? "common" : tabs[1]?.id ?? "common";
84
+ });
85
+ useEffect(() => {
86
+ const validTab = tabs.find((tab) => tab.id === currentTab);
87
+ if (!validTab) {
88
+ const commonHasProps = Boolean(tabs[0]?.properties?.length);
89
+ setCurrentTab(commonHasProps ? "common" : tabs[1]?.id ?? "common");
90
+ }
91
+ }, [tabs, currentTab]);
92
+ return (React.createElement(Box, { as: "form", onSubmit: submit, flex: true, flexDirection: "column" },
93
+ React.createElement(DrawerContent, null,
94
+ action?.showInDrawer ? React.createElement(ActionHeader, { ...props }) : null,
95
+ action.layout ? (action.layout.map((layoutElement, i) => (React.createElement(LayoutElementRenderer
96
+ // eslint-disable-next-line react/no-array-index-key
97
+ , {
98
+ // eslint-disable-next-line react/no-array-index-key
99
+ key: i, layoutElement: layoutElement, ...props, where: "edit", onChange: handleChange, record: record })))) : (React.createElement(Tabs, { currentTab: currentTab, onChange: setCurrentTab, buttonComponent: TabButton, contentComponent: StyledTabsContent }, tabs.map((tab) => (React.createElement(Tab, { key: tab.id, id: tab.id, label: tab.label }, tab.properties.map((property) => (React.createElement(BasePropertyComponent, { key: property.propertyPath, where: "edit", onChange: handleChange, property: property, resource: resource, record: record }))))))))),
100
+ React.createElement(DrawerFooter, null,
101
+ React.createElement(Button, { variant: "contained", type: "submit", "data-testid": "button-save", disabled: loading },
102
+ loading ? React.createElement(Icon, { icon: "Loader", spin: true }) : null,
103
+ translateButton("save", resource.id)))));
104
+ };
105
+ export default FeatureTabsEdit;
@@ -0,0 +1,8 @@
1
+ import { ComponentLoader, FeatureType } from "adminjs";
2
+ type FeatureTabsOptions = {
3
+ componentLoader?: ComponentLoader;
4
+ commonTabLabel?: string;
5
+ };
6
+ declare const FeatureTabsFeature: (config: FeatureTabsOptions) => FeatureType;
7
+ export declare const FeatureTabs: (config: FeatureTabsOptions) => FeatureType;
8
+ export default FeatureTabsFeature;
@@ -0,0 +1,28 @@
1
+ import { buildFeature } from "adminjs";
2
+ import { bundleComponent } from "../../utils/bundle-component.js";
3
+ const COMPONENT_NAME = "FeatureTabs";
4
+ const FeatureTabsFeature = (config) => {
5
+ const { componentLoader, commonTabLabel } = config;
6
+ const editComponent = bundleComponent(componentLoader, COMPONENT_NAME, "FeatureTabsEdit.js");
7
+ const showComponent = bundleComponent(componentLoader, COMPONENT_NAME, "FeatureTabsShow.js");
8
+ return buildFeature({
9
+ actions: {
10
+ edit: {
11
+ component: editComponent,
12
+ },
13
+ show: {
14
+ component: showComponent,
15
+ },
16
+ },
17
+ properties: {
18
+ __featureTabsCommonLabel: {
19
+ isVisible: false,
20
+ custom: {
21
+ value: commonTabLabel,
22
+ },
23
+ },
24
+ },
25
+ });
26
+ };
27
+ export const FeatureTabs = FeatureTabsFeature;
28
+ export default FeatureTabsFeature;
@@ -0,0 +1,4 @@
1
+ import { FC } from "react";
2
+ import { ActionProps } from "adminjs";
3
+ export declare const FeatureTabsShow: FC<ActionProps>;
4
+ export default FeatureTabsShow;