@rebasepro/admin 0.6.0 → 0.6.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 +7 -3
- package/dist/{CollectionEditorDialog-jA-PLh6N.js → CollectionEditorDialog-HNXGxXdO.js} +3 -3
- package/dist/{CollectionEditorDialog-jA-PLh6N.js.map → CollectionEditorDialog-HNXGxXdO.js.map} +1 -1
- package/dist/{CollectionsStudioView-UKouBPOm.js → CollectionsStudioView-B1mN33GB.js} +4 -4
- package/dist/{CollectionsStudioView-UKouBPOm.js.map → CollectionsStudioView-B1mN33GB.js.map} +1 -1
- package/dist/{PropertyEditView-DEUddmg_.js → PropertyEditView-C2wp8kQ9.js} +2 -2
- package/dist/{PropertyEditView-DEUddmg_.js.map → PropertyEditView-C2wp8kQ9.js.map} +1 -1
- package/dist/collection_editor_ui.js +3 -3
- package/dist/editor/editor.d.ts +10 -4
- package/dist/editor.js +6 -4
- package/dist/editor.js.map +1 -1
- package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +2 -2
- package/dist/{history-BL49TIDb.js → history-BO6VT85a.js} +2 -2
- package/dist/{history-BL49TIDb.js.map → history-BO6VT85a.js.map} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/{src-BJ8fkM8y.js → src-BYniefVu.js} +56 -55
- package/dist/src-BYniefVu.js.map +1 -0
- package/package.json +8 -8
- package/src/collection_editor/ui/AddKanbanColumnAction.tsx +2 -0
- package/src/components/ArrayContainer.tsx +5 -5
- package/src/components/DrawerNavigationItem.tsx +4 -4
- package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +2 -0
- package/src/components/HomePage/NavigationCard.tsx +8 -14
- package/src/components/HomePage/NavigationGroup.tsx +1 -1
- package/src/components/HomePage/SmallNavigationCard.tsx +1 -5
- package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +28 -21
- package/src/components/common/default_entity_actions.tsx +10 -2
- package/src/editor/editor.tsx +14 -8
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +4 -4
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +1 -1
- package/src/index.ts +2 -2
- package/dist/src-BJ8fkM8y.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rebasepro/admin",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.6.
|
|
4
|
+
"version": "0.6.1",
|
|
5
5
|
"description": "Rebase CMS — content management views, forms, and routing",
|
|
6
6
|
"funding": {
|
|
7
7
|
"url": "https://github.com/sponsors/rebaseco"
|
|
@@ -83,13 +83,13 @@
|
|
|
83
83
|
"react-dropzone": "^15.0.0",
|
|
84
84
|
"react-use-measure": "^2.1.7",
|
|
85
85
|
"zod": "^4.4.3",
|
|
86
|
-
"@rebasepro/
|
|
87
|
-
"@rebasepro/
|
|
88
|
-
"@rebasepro/
|
|
89
|
-
"@rebasepro/
|
|
90
|
-
"@rebasepro/types": "0.6.
|
|
91
|
-
"@rebasepro/
|
|
92
|
-
"@rebasepro/
|
|
86
|
+
"@rebasepro/core": "0.6.1",
|
|
87
|
+
"@rebasepro/formex": "0.6.1",
|
|
88
|
+
"@rebasepro/schema-inference": "0.6.1",
|
|
89
|
+
"@rebasepro/common": "0.6.1",
|
|
90
|
+
"@rebasepro/types": "0.6.1",
|
|
91
|
+
"@rebasepro/utils": "0.6.1",
|
|
92
|
+
"@rebasepro/ui": "0.6.1"
|
|
93
93
|
},
|
|
94
94
|
"peerDependencies": {
|
|
95
95
|
"react": ">=19.0.0",
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
Dialog,
|
|
16
16
|
DialogActions,
|
|
17
17
|
DialogContent,
|
|
18
|
+
DialogTitle,
|
|
18
19
|
IconButton,
|
|
19
20
|
PlusIcon,
|
|
20
21
|
TextField,
|
|
@@ -159,6 +160,7 @@ export function AddKanbanColumnAction({
|
|
|
159
160
|
</div>
|
|
160
161
|
|
|
161
162
|
<Dialog open={dialogOpen} onOpenChange={setDialogOpen}>
|
|
163
|
+
<DialogTitle hidden>{t("studio_add_kanban_column_title")}</DialogTitle>
|
|
162
164
|
<DialogContent className="max-w-md">
|
|
163
165
|
<Typography variant="h6" className="mb-4">
|
|
164
166
|
{t("studio_add_kanban_column_title")}
|
|
@@ -402,13 +402,13 @@ export function ArrayContainer<T>({
|
|
|
402
402
|
const newIds = [...internalIds];
|
|
403
403
|
newIds.splice(index, 1);
|
|
404
404
|
setInternalIds(newIds);
|
|
405
|
-
onValueChange(value.filter((_, i) => i !== index));
|
|
405
|
+
onValueChange((value ?? []).filter((_, i) => i !== index));
|
|
406
406
|
};
|
|
407
407
|
|
|
408
408
|
const copy = (index: number) => {
|
|
409
409
|
if ((value ?? []).length >= max) return;
|
|
410
410
|
const id = getRandomId();
|
|
411
|
-
const copyingItem = value[index];
|
|
411
|
+
const copyingItem = (value ?? [])[index];
|
|
412
412
|
const newIds: number[] = [
|
|
413
413
|
...internalIds.slice(0, index + 1),
|
|
414
414
|
id,
|
|
@@ -416,7 +416,7 @@ export function ArrayContainer<T>({
|
|
|
416
416
|
];
|
|
417
417
|
if (onInternalIdAdded) onInternalIdAdded(id);
|
|
418
418
|
setInternalIds(newIds);
|
|
419
|
-
onValueChange([...value.slice(0, index + 1), copyingItem, ...value.slice(index + 1)]);
|
|
419
|
+
onValueChange([...(value ?? []).slice(0, index + 1), copyingItem, ...(value ?? []).slice(index + 1)]);
|
|
420
420
|
};
|
|
421
421
|
|
|
422
422
|
const addInIndex = (index: number) => {
|
|
@@ -429,7 +429,7 @@ export function ArrayContainer<T>({
|
|
|
429
429
|
];
|
|
430
430
|
if (onInternalIdAdded) onInternalIdAdded(id);
|
|
431
431
|
setInternalIds(newIds);
|
|
432
|
-
onValueChange([...value.slice(0, index), newDefaultEntry, ...value.slice(index)]);
|
|
432
|
+
onValueChange([...(value ?? []).slice(0, index), newDefaultEntry, ...(value ?? []).slice(index)]);
|
|
433
433
|
};
|
|
434
434
|
|
|
435
435
|
const onDragEnd = (event: DragEndEvent) => {
|
|
@@ -444,7 +444,7 @@ export function ArrayContainer<T>({
|
|
|
444
444
|
if (oldIndex === -1 || newIndex === -1) return;
|
|
445
445
|
const newIds = arrayMove(internalIds, oldIndex, newIndex);
|
|
446
446
|
setInternalIds(newIds);
|
|
447
|
-
onValueChange(arrayMove(value, oldIndex, newIndex));
|
|
447
|
+
onValueChange(arrayMove(value ?? [], oldIndex, newIndex));
|
|
448
448
|
};
|
|
449
449
|
|
|
450
450
|
return sortable ? (
|
|
@@ -22,7 +22,7 @@ export function DrawerNavigationItem({
|
|
|
22
22
|
}) {
|
|
23
23
|
|
|
24
24
|
const iconWrap = <div
|
|
25
|
-
className={"shrink-0 flex items-center justify-center w-[44px] h-[30px] text-surface-500 dark:text-text-secondary-dark [&>svg]:size-4"}>
|
|
25
|
+
className={"shrink-0 flex items-center justify-center w-[44px] h-[30px] text-surface-500 dark:text-text-secondary-dark [&>svg]:size-4 group-hover/nav:text-primary transition-colors duration-150"}>
|
|
26
26
|
{icon}
|
|
27
27
|
</div>;
|
|
28
28
|
|
|
@@ -33,12 +33,12 @@ export function DrawerNavigationItem({
|
|
|
33
33
|
width: "100%",
|
|
34
34
|
transition: drawerOpen ? "width 150ms ease-in" : undefined
|
|
35
35
|
}}
|
|
36
|
-
className={({ isActive }: { isActive: boolean }) => cls("rounded-
|
|
37
|
-
"hover:bg-
|
|
36
|
+
className={({ isActive }: { isActive: boolean }) => cls("rounded-lg truncate group/nav",
|
|
37
|
+
"hover:bg-primary/5 dark:hover:bg-primary/5 text-surface-700 dark:text-surface-300 hover:text-surface-900 dark:hover:text-white",
|
|
38
38
|
"flex flex-row items-center",
|
|
39
39
|
drawerOpen ? "pr-4 h-[30px]" : "h-[30px]",
|
|
40
40
|
"font-medium text-[13px]",
|
|
41
|
-
isActive ? "bg-
|
|
41
|
+
isActive ? "bg-primary/8 dark:bg-primary/10 text-primary dark:text-primary [&_div]:text-primary" : ""
|
|
42
42
|
)}
|
|
43
43
|
to={url}
|
|
44
44
|
>
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
Dialog,
|
|
14
14
|
DialogActions,
|
|
15
15
|
DialogContent,
|
|
16
|
+
DialogTitle,
|
|
16
17
|
getColorSchemeForSeed,
|
|
17
18
|
IconButton,
|
|
18
19
|
iconSize,
|
|
@@ -626,6 +627,7 @@ parentEntityIds,
|
|
|
626
627
|
|
|
627
628
|
{/* Backfill dialog */}
|
|
628
629
|
<Dialog open={showBackfillDialog} onOpenChange={setShowBackfillDialog}>
|
|
630
|
+
<DialogTitle hidden>{t("initialize_kanban_order")}</DialogTitle>
|
|
629
631
|
<DialogContent>
|
|
630
632
|
<Typography variant="h6" className="mb-4">{t("initialize_kanban_order")}</Typography>
|
|
631
633
|
<Typography variant="body2">
|
|
@@ -25,10 +25,8 @@ export const NavigationCard = React.memo(function NavigationCard({
|
|
|
25
25
|
return (
|
|
26
26
|
<Card
|
|
27
27
|
className={cls(
|
|
28
|
-
"group h-full p-4 cursor-pointer transition-
|
|
29
|
-
"
|
|
30
|
-
"hover:shadow-md hover:shadow-black/[0.04]",
|
|
31
|
-
"hover:border-surface-300 dark:hover:border-primary/20",
|
|
28
|
+
"group h-full p-4 cursor-pointer transition-colors duration-150 ease-in-out",
|
|
29
|
+
"hover:bg-primary/5 dark:hover:bg-primary/5",
|
|
32
30
|
shrink && "w-full max-w-full min-h-0 scale-75"
|
|
33
31
|
)}
|
|
34
32
|
onClick={() => {
|
|
@@ -39,8 +37,8 @@ export const NavigationCard = React.memo(function NavigationCard({
|
|
|
39
37
|
<div className="flex flex-col h-full">
|
|
40
38
|
{/* Header: title + icon left, actions right */}
|
|
41
39
|
<div className="flex items-center w-full justify-between mb-1">
|
|
42
|
-
<div className="flex items-center gap-
|
|
43
|
-
<div className="flex items-center justify-center w-
|
|
40
|
+
<div className="flex items-center gap-3">
|
|
41
|
+
<div className="flex items-center justify-center w-5 h-5 text-surface-400 dark:text-surface-500 transition-colors duration-150 group-hover:text-primary dark:group-hover:text-primary">
|
|
44
42
|
{icon}
|
|
45
43
|
</div>
|
|
46
44
|
<Typography variant="subtitle1"
|
|
@@ -60,7 +58,7 @@ export const NavigationCard = React.memo(function NavigationCard({
|
|
|
60
58
|
</div>
|
|
61
59
|
|
|
62
60
|
{/* Description */}
|
|
63
|
-
<div className="
|
|
61
|
+
<div className="pl-8">
|
|
64
62
|
{description && <Typography variant="caption"
|
|
65
63
|
color="secondary"
|
|
66
64
|
component="div">
|
|
@@ -69,17 +67,13 @@ export const NavigationCard = React.memo(function NavigationCard({
|
|
|
69
67
|
</div>
|
|
70
68
|
|
|
71
69
|
{additionalContent && (
|
|
72
|
-
<div className="pl-
|
|
70
|
+
<div className="pl-8 pointer-events-none">
|
|
73
71
|
{additionalContent}
|
|
74
72
|
</div>
|
|
75
73
|
)}
|
|
76
74
|
|
|
77
|
-
{/*
|
|
78
|
-
<div className="
|
|
79
|
-
<div className={"transition-transform duration-200 group-hover:translate-x-0.5"}>
|
|
80
|
-
<ArrowRightIcon className="text-primary" size={iconSize.small}/>
|
|
81
|
-
</div>
|
|
82
|
-
</div>
|
|
75
|
+
{/* Spacer pushes content above to align at the top across grid siblings */}
|
|
76
|
+
<div className="grow"/>
|
|
83
77
|
|
|
84
78
|
</div>
|
|
85
79
|
|
|
@@ -40,7 +40,7 @@ export function NavigationGroup({
|
|
|
40
40
|
color="secondary"
|
|
41
41
|
className={cls(
|
|
42
42
|
"px-4 py-1 rounded",
|
|
43
|
-
"font-
|
|
43
|
+
"font-medium text-[10px] uppercase tracking-[0.08em] text-primary/50 dark:text-primary/70"
|
|
44
44
|
)}
|
|
45
45
|
>
|
|
46
46
|
{currentGroupName}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { cardClickableMixin, cardMixin, cls, Typography } from "@rebasepro/ui";
|
|
2
2
|
|
|
3
3
|
import { Link } from "react-router-dom";
|
|
4
4
|
|
|
@@ -35,11 +35,7 @@ export function SmallNavigationCard({
|
|
|
35
35
|
</Typography>
|
|
36
36
|
</div>
|
|
37
37
|
|
|
38
|
-
<div className={"p-2"}>
|
|
39
|
-
<ArrowRightIcon className="text-primary"/>
|
|
40
|
-
</div>
|
|
41
38
|
</Link>
|
|
42
39
|
|
|
43
40
|
</>);
|
|
44
41
|
}
|
|
45
|
-
|
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
|
|
2
1
|
import React, { useState } from "react";
|
|
3
2
|
import { EnumValuesChip } from "../../../preview";
|
|
4
|
-
import {
|
|
5
|
-
|
|
3
|
+
import {
|
|
4
|
+
IconButton,
|
|
5
|
+
MultiSelect,
|
|
6
|
+
MultiSelectItem,
|
|
7
|
+
Select,
|
|
8
|
+
SelectItem,
|
|
9
|
+
TextField,
|
|
10
|
+
VirtualTableWhereFilterOp,
|
|
11
|
+
XIcon
|
|
12
|
+
} from "@rebasepro/ui";
|
|
6
13
|
import { EnumValueConfig } from "@rebasepro/types";
|
|
7
14
|
import { useTranslation } from "@rebasepro/core";
|
|
8
15
|
|
|
@@ -33,14 +40,14 @@ const operationLabels = {
|
|
|
33
40
|
const multipleSelectOperations = ["array-contains-any", "in", "not-in"];
|
|
34
41
|
|
|
35
42
|
export function StringNumberFilterField({
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}: StringNumberFilterFieldProps) {
|
|
43
|
+
name,
|
|
44
|
+
value,
|
|
45
|
+
setValue,
|
|
46
|
+
type,
|
|
47
|
+
isArray,
|
|
48
|
+
enumValues,
|
|
49
|
+
title
|
|
50
|
+
}: StringNumberFilterFieldProps) {
|
|
44
51
|
const { t } = useTranslation();
|
|
45
52
|
|
|
46
53
|
const possibleOperations: (keyof typeof operationLabels)[] = isArray
|
|
@@ -110,13 +117,13 @@ export function StringNumberFilterField({
|
|
|
110
117
|
<div className="flex w-full">
|
|
111
118
|
<div className={"w-[100px]"}>
|
|
112
119
|
<Select value={operation}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
+
size={"medium"}
|
|
121
|
+
fullWidth={true}
|
|
122
|
+
position={"item-aligned"}
|
|
123
|
+
onValueChange={(value) => {
|
|
124
|
+
updateFilter(value as VirtualTableWhereFilterOp | "is-null", internalValue);
|
|
125
|
+
}}
|
|
126
|
+
renderValue={(op) => operationLabels[op as keyof typeof operationLabels]}>
|
|
120
127
|
{possibleOperations.map((op) => (
|
|
121
128
|
<SelectItem key={op} value={op}>
|
|
122
129
|
{operationLabels[op]}
|
|
@@ -174,7 +181,7 @@ export function StringNumberFilterField({
|
|
|
174
181
|
}}>
|
|
175
182
|
{enumValues.map((enumConfig) => (
|
|
176
183
|
<SelectItem key={`select_item_${name}_${enumConfig.id}`}
|
|
177
|
-
|
|
184
|
+
value={String(enumConfig.id)}>
|
|
178
185
|
<EnumValuesChip
|
|
179
186
|
enumKey={String(enumConfig.id)}
|
|
180
187
|
enumValues={enumValues}
|
|
@@ -191,7 +198,7 @@ export function StringNumberFilterField({
|
|
|
191
198
|
value={Array.isArray(internalValue) ? internalValue.map(e => String(e)) : []}
|
|
192
199
|
disabled={isNullOperation}
|
|
193
200
|
onValueChange={(value) => {
|
|
194
|
-
updateFilter(operation, type === "number" ? value.map(v => parseInt(v)) : value)
|
|
201
|
+
updateFilter(operation, type === "number" ? (value ?? []).map(v => parseInt(v)) : value)
|
|
195
202
|
}}
|
|
196
203
|
multiple={multiple}
|
|
197
204
|
endAdornment={internalValue && <IconButton
|
|
@@ -202,7 +209,7 @@ export function StringNumberFilterField({
|
|
|
202
209
|
>
|
|
203
210
|
{enumValues.map((enumConfig) => (
|
|
204
211
|
<MultiSelectItem key={`select_value_${name}_${enumConfig.id}`}
|
|
205
|
-
|
|
212
|
+
value={String(enumConfig.id)}>
|
|
206
213
|
<EnumValuesChip
|
|
207
214
|
enumKey={String(enumConfig.id)}
|
|
208
215
|
enumValues={enumValues}
|
|
@@ -125,7 +125,8 @@ export const deleteEntityAction: EntityAction = {
|
|
|
125
125
|
context,
|
|
126
126
|
selectionController,
|
|
127
127
|
onCollectionChange,
|
|
128
|
-
navigateBack
|
|
128
|
+
navigateBack,
|
|
129
|
+
openEntityMode
|
|
129
130
|
}): Promise<void> {
|
|
130
131
|
if (!entity) {
|
|
131
132
|
throw new Error("INTERNAL: deleteEntityAction: Entity is undefined");
|
|
@@ -150,7 +151,14 @@ export const deleteEntityAction: EntityAction = {
|
|
|
150
151
|
});
|
|
151
152
|
selectionController?.setSelectedEntities(selectionController.selectedEntities.filter(e => e.id !== entity.id));
|
|
152
153
|
onCollectionChange?.();
|
|
153
|
-
navigateBack
|
|
154
|
+
// In full-screen mode, navigateBack would go to the deleted entity's
|
|
155
|
+
// detail URL, which no longer exists. Navigate to the parent collection instead.
|
|
156
|
+
if (openEntityMode === "full_screen" && context.urlController) {
|
|
157
|
+
const collectionUrl = context.urlController.buildUrlCollectionPath(path);
|
|
158
|
+
context.urlController.navigate(collectionUrl, { replace: true });
|
|
159
|
+
} else {
|
|
160
|
+
navigateBack?.();
|
|
161
|
+
}
|
|
154
162
|
}}
|
|
155
163
|
onClose={closeDialog}/>;
|
|
156
164
|
}
|
package/src/editor/editor.tsx
CHANGED
|
@@ -25,22 +25,26 @@ export interface MarkdownEditorConfig {
|
|
|
25
25
|
transformPastedText?: boolean;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
export type
|
|
28
|
+
export type RichTextEditorTextSize = "sm" | "base" | "lg";
|
|
29
|
+
/** @deprecated Use `RichTextEditorTextSize` instead. */
|
|
30
|
+
export type RebaseEditorTextSize = RichTextEditorTextSize;
|
|
29
31
|
|
|
30
|
-
export type
|
|
32
|
+
export type RichTextEditorProps = {
|
|
31
33
|
content?: JSONContent | string,
|
|
32
34
|
onMarkdownContentChange?: (content: string) => void,
|
|
33
35
|
onJsonContentChange?: (content: JSONContent | null) => void,
|
|
34
36
|
onHtmlContentChange?: (content: string) => void,
|
|
35
37
|
handleImageUpload: (file: File) => Promise<string>,
|
|
36
38
|
version?: number,
|
|
37
|
-
textSize?:
|
|
39
|
+
textSize?: RichTextEditorTextSize,
|
|
38
40
|
highlight?: { from: number, to: number },
|
|
39
41
|
aiController?: EditorAIController,
|
|
40
42
|
customComponents?: CustomEditorComponent[];
|
|
41
43
|
disabled?: boolean;
|
|
42
44
|
markdownConfig?: MarkdownEditorConfig;
|
|
43
45
|
};
|
|
46
|
+
/** @deprecated Use `RichTextEditorProps` instead. */
|
|
47
|
+
export type RebaseEditorProps = RichTextEditorProps;
|
|
44
48
|
|
|
45
49
|
const proseClasses = {
|
|
46
50
|
"sm": "prose-sm",
|
|
@@ -48,7 +52,7 @@ const proseClasses = {
|
|
|
48
52
|
"lg": "prose-lg"
|
|
49
53
|
}
|
|
50
54
|
|
|
51
|
-
export const
|
|
55
|
+
export const RichTextEditor = ({
|
|
52
56
|
content,
|
|
53
57
|
onJsonContentChange,
|
|
54
58
|
onHtmlContentChange,
|
|
@@ -60,7 +64,8 @@ export const RebaseEditor = ({
|
|
|
60
64
|
aiController,
|
|
61
65
|
disabled,
|
|
62
66
|
markdownConfig
|
|
63
|
-
}:
|
|
67
|
+
}: RichTextEditorProps) => {
|
|
68
|
+
|
|
64
69
|
const { t } = useTranslation();
|
|
65
70
|
|
|
66
71
|
const [openNode, setOpenNode] = useState(false);
|
|
@@ -134,7 +139,7 @@ onJsonContentChange };
|
|
|
134
139
|
const markdown = serializer.serialize(currentState.doc);
|
|
135
140
|
onMarkdownContentChange(markdown);
|
|
136
141
|
} catch (e) {
|
|
137
|
-
console.warn("[
|
|
142
|
+
console.warn("[RichTextEditor] Could not serialize editor state to markdown:", e);
|
|
138
143
|
}
|
|
139
144
|
}
|
|
140
145
|
if (onJsonContentChange) {
|
|
@@ -168,7 +173,7 @@ onJsonContentChange };
|
|
|
168
173
|
view.dispatch(tr);
|
|
169
174
|
}
|
|
170
175
|
} catch (e) {
|
|
171
|
-
console.warn("[
|
|
176
|
+
console.warn("[RichTextEditor] Could not reset editor content:", e);
|
|
172
177
|
}
|
|
173
178
|
// Also reset raw-markdown textarea if the user is in source mode
|
|
174
179
|
if (isMarkdownMode) {
|
|
@@ -319,7 +324,8 @@ view }), [state, view])}>
|
|
|
319
324
|
</div>
|
|
320
325
|
);
|
|
321
326
|
};
|
|
322
|
-
|
|
327
|
+
/** @deprecated Use `RichTextEditor` instead. */
|
|
328
|
+
export const RebaseEditor = RichTextEditor;
|
|
323
329
|
|
|
324
330
|
const cssStyles = `
|
|
325
331
|
.ProseMirror {
|
|
@@ -13,13 +13,13 @@ import {
|
|
|
13
13
|
Skeleton,
|
|
14
14
|
XIcon
|
|
15
15
|
} from "@rebasepro/ui";
|
|
16
|
-
import type {
|
|
16
|
+
import type { RichTextEditorProps } from "../../editor";
|
|
17
17
|
import { resolveStorageFilenameString, resolveStoragePathString } from "@rebasepro/common";
|
|
18
18
|
import { randomString } from "@rebasepro/utils";
|
|
19
19
|
|
|
20
20
|
// Lazy-load ProseMirror editor + markdown parser/serializer (~300KB)
|
|
21
21
|
// Only fetched when a markdown field is actually rendered.
|
|
22
|
-
const
|
|
22
|
+
const RichTextEditor = lazy(() => import("../../editor").then(m => ({ default: m.RichTextEditor })));
|
|
23
23
|
const loadMarkdownUtils = () => import("../../editor/markdown");
|
|
24
24
|
let _markdownUtils: Awaited<ReturnType<typeof loadMarkdownUtils>> | null = null;
|
|
25
25
|
const getMarkdownUtils = async () => {
|
|
@@ -29,7 +29,7 @@ const getMarkdownUtils = async () => {
|
|
|
29
29
|
|
|
30
30
|
interface MarkdownEditorFieldProps {
|
|
31
31
|
highlight?: { from: number, to: number };
|
|
32
|
-
editorProps?: Partial<
|
|
32
|
+
editorProps?: Partial<RichTextEditorProps>
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
/**
|
|
@@ -173,7 +173,7 @@ export function MarkdownEditorFieldBinding({
|
|
|
173
173
|
}, [entityId, entityValues, path, property, propertyKey, storage]);
|
|
174
174
|
|
|
175
175
|
const editor = <Suspense fallback={<Skeleton height={200} className="w-full rounded-md"/>}>
|
|
176
|
-
<
|
|
176
|
+
<RichTextEditor
|
|
177
177
|
content={value}
|
|
178
178
|
onMarkdownContentChange={onContentChange}
|
|
179
179
|
version={context.formex.version + fieldVersion}
|
|
@@ -481,7 +481,7 @@ export function StorageUpload({
|
|
|
481
481
|
onDragStart={handleDragStart}
|
|
482
482
|
onDragEnd={handleDragEnd}
|
|
483
483
|
>
|
|
484
|
-
<SortableContext items={value.map(v => v.id)} strategy={horizontalListSortingStrategy}>
|
|
484
|
+
<SortableContext items={(value ?? []).map(v => v.id)} strategy={horizontalListSortingStrategy}>
|
|
485
485
|
<FileDropComponent {...fileDropProps}/>
|
|
486
486
|
</SortableContext>
|
|
487
487
|
</DndContext>
|
package/src/index.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// CMS-specific types take priority over base types when names conflict
|
|
2
2
|
export * from "./types";
|
|
3
|
-
// Editor types only — the full ProseMirror editor is a heavy import (~300 KB)
|
|
3
|
+
// Editor types only — the full ProseMirror editor (RichTextEditor) is a heavy import (~300 KB)
|
|
4
4
|
// and is available as a separate entry point: @rebasepro/admin/editor
|
|
5
|
-
export type { RebaseEditorProps, JSONContent, EditorAIController } from "./editor";
|
|
5
|
+
export type { RichTextEditorProps, RichTextEditorTextSize, RebaseEditorProps, RebaseEditorTextSize, JSONContent, EditorAIController } from "./editor";
|
|
6
6
|
export * from "./form";
|
|
7
7
|
export * from "./preview";
|
|
8
8
|
export * from "./routes";
|