@rebasepro/admin 0.12.1-canary.gf5f1d39 → 0.13.0
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 +1 -1
- package/dist/{CollectionEditorDialog-Dpc75wIZ.js → CollectionEditorDialog-CjXkWZ64.js} +75 -62
- package/dist/{CollectionEditorDialog-Dpc75wIZ.js.map → CollectionEditorDialog-CjXkWZ64.js.map} +1 -1
- package/dist/{PropertyEditView-DH3XZC2x.js → PropertyEditView-W8I3YV89.js} +36 -16
- package/dist/{PropertyEditView-DH3XZC2x.js.map → PropertyEditView-W8I3YV89.js.map} +1 -1
- package/dist/{RouterCollectionsStudioView-BZLq4MGp.js → RouterCollectionsStudioView-BsLTNoqX.js} +5 -5
- package/dist/{RouterCollectionsStudioView-BZLq4MGp.js.map → RouterCollectionsStudioView-BsLTNoqX.js.map} +1 -1
- package/dist/collection_editor/serializable_types.d.ts +4 -1
- package/dist/collection_editor/ui/collection_editor/CollectionRelationsTab.d.ts +1 -0
- package/dist/collection_editor/useLocalCollectionsConfigController.d.ts +8 -0
- package/dist/collection_editor_ui.js +5 -5
- package/dist/collection_editor_ui.js.map +1 -1
- package/dist/components/CollectionTableBinding/column_utils.d.ts +17 -0
- package/dist/components/CollectionViewBinding/CollectionViewStartActions.d.ts +7 -2
- package/dist/components/CollectionViewBinding/SortButton.d.ts +24 -0
- package/dist/components/CollectionViewBinding/SplitListCloseButton.d.ts +10 -0
- package/dist/components/CollectionViewBinding/SplitViewContext.d.ts +23 -0
- package/dist/components/CollectionViewBinding/hooks/useKanbanDragAndDrop.d.ts +26 -0
- package/dist/components/DetailViewBinding.d.ts +5 -0
- package/dist/components/EditFormActions.d.ts +12 -1
- package/dist/components/EditViewBinding.d.ts +6 -1
- package/dist/components/EntityIdentityBar.d.ts +53 -0
- package/dist/components/EntityInspector.d.ts +35 -0
- package/dist/components/EntityPreviewNesting.d.ts +25 -0
- package/dist/components/EntityViewBinding.d.ts +9 -0
- package/dist/components/InlineEntityPreview.d.ts +47 -0
- package/dist/components/history/EntityHistoryView.d.ts +4 -1
- package/dist/components/index.d.ts +2 -0
- package/dist/editor.js +18 -10
- package/dist/editor.js.map +1 -1
- package/dist/{export-BzIpUdSK.js → export-J79rMoNj.js} +2 -2
- package/dist/{export-BzIpUdSK.js.map → export-J79rMoNj.js.map} +1 -1
- package/dist/form/EntityForm.d.ts +1 -1
- package/dist/form/EntityFormActions.d.ts +11 -1
- package/dist/form/PropertyFieldBinding.d.ts +1 -1
- package/dist/form/components/FieldBlock.d.ts +30 -0
- package/dist/form/components/FormRail.d.ts +18 -0
- package/dist/form/components/FormSections.d.ts +16 -0
- package/dist/form/components/index.d.ts +3 -2
- package/dist/form/components/useRailVisible.d.ts +24 -0
- package/dist/form/field_bindings/BinaryFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/DateTimeFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/GeopointFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MultiSelectFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/ReadOnlyFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/SelectFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/SwitchFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/TextFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/UserSelectFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/VectorFieldBinding.d.ts +1 -1
- package/dist/{history-g9688IaK.js → history-D7L_JlLO.js} +35 -33
- package/dist/history-D7L_JlLO.js.map +1 -0
- package/dist/hooks/navigation/utils.d.ts +16 -0
- package/dist/hooks/useBuildSidePanel.d.ts +14 -0
- package/dist/hooks/useEntityDisplayTitle.d.ts +18 -0
- package/dist/hooks/useHistory.d.ts +7 -0
- package/dist/hooks/useRecordActions.d.ts +17 -0
- package/dist/{import-BjUG-cIY.js → import-BvYl--U4.js} +2 -2
- package/dist/{import-BjUG-cIY.js.map → import-BvYl--U4.js.map} +1 -1
- package/dist/index.js +106 -35
- package/dist/index.js.map +1 -1
- package/dist/markdown-CklalUUk.js.map +1 -1
- package/dist/preview/components/InlineEntityListPreview.d.ts +15 -0
- package/dist/preview/index.d.ts +1 -0
- package/dist/preview/property_previews/ArrayOfReferencesPreview.d.ts +1 -1
- package/dist/preview/property_previews/ArrayOfRelationsPreview.d.ts +1 -1
- package/dist/types/components/EntityFormActionsProps.d.ts +0 -1
- package/dist/types/components/EntityFormProps.d.ts +0 -5
- package/dist/types/fields.d.ts +24 -0
- package/dist/{util-B5fJm1FA.js → util-GiwPgxnL.js} +2106 -1117
- package/dist/util-GiwPgxnL.js.map +1 -0
- package/package.json +32 -34
- package/src/collection_editor/ConfigControllerProvider.tsx +1 -1
- package/src/collection_editor/serializable_types.ts +4 -3
- package/src/collection_editor/serializable_utils.ts +51 -17
- package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +65 -22
- package/src/collection_editor/ui/collection_editor/CollectionRLSTab.tsx +38 -30
- package/src/collection_editor/ui/collection_editor/CollectionRelationsTab.tsx +3 -1
- package/src/collection_editor/ui/collection_editor/RouterCollectionStudioView.tsx +1 -1
- package/src/collection_editor/ui/collection_editor/RouterCollectionsStudioView.tsx +1 -1
- package/src/collection_editor/ui/collection_editor/properties/RelationPropertyField.tsx +16 -0
- package/src/collection_editor/useLocalCollectionsConfigController.tsx +127 -15
- package/src/collection_editor/validateCollectionJson.ts +3 -3
- package/src/components/AdminModeSyncer.tsx +1 -1
- package/src/components/CollectionTableBinding/PropertyTableCell.tsx +10 -2
- package/src/components/CollectionTableBinding/column_utils.tsx +59 -2
- package/src/components/CollectionTableBinding/table_bindings.tsx +2 -1
- package/src/components/CollectionViewBinding/CollectionBoardViewBinding.tsx +23 -16
- package/src/components/CollectionViewBinding/CollectionViewActions.tsx +7 -1
- package/src/components/CollectionViewBinding/CollectionViewBinding.tsx +9 -2
- package/src/components/CollectionViewBinding/CollectionViewStartActions.tsx +47 -12
- package/src/components/CollectionViewBinding/SortButton.tsx +189 -0
- package/src/components/CollectionViewBinding/SplitListCloseButton.tsx +33 -0
- package/src/components/CollectionViewBinding/SplitListView.tsx +18 -3
- package/src/components/CollectionViewBinding/SplitViewContext.tsx +34 -0
- package/src/components/CollectionViewBinding/hooks/useKanbanDragAndDrop.ts +48 -9
- package/src/components/CollectionViewBinding/useBoardDataController.tsx +80 -25
- package/src/components/CollectionViewBinding/usePreviewSlots.ts +18 -6
- package/src/components/DefaultAppBar.tsx +1 -1
- package/src/components/DefaultDrawer.tsx +1 -1
- package/src/components/DetailViewBinding.tsx +112 -148
- package/src/components/DrawerNavigationItem.tsx +1 -1
- package/src/components/EditFormActions.tsx +54 -129
- package/src/components/EditViewBinding.tsx +202 -99
- package/src/components/EntityIdentityBar.tsx +288 -0
- package/src/components/EntityInspector.tsx +137 -0
- package/src/components/EntityPreviewBinding.tsx +6 -2
- package/src/components/EntityPreviewNesting.tsx +50 -0
- package/src/components/EntityViewBinding.tsx +35 -32
- package/src/components/HomePage/FavouritesView.tsx +1 -1
- package/src/components/HomePage/NavigationCardBinding.tsx +1 -1
- package/src/components/HomePage/SmallNavigationCard.tsx +1 -1
- package/src/components/InlineEntityPreview.tsx +149 -0
- package/src/components/RebaseLayout.tsx +1 -1
- package/src/components/RebaseNavigation.tsx +45 -5
- package/src/components/RebaseRouteDefs.tsx +1 -1
- package/src/components/SelectableTable/SelectableTable.tsx +2 -2
- package/src/components/SidePanelBinding.tsx +19 -13
- package/src/components/UserSelector.tsx +12 -6
- package/src/components/common/default_entity_actions.tsx +4 -3
- package/src/components/history/EntityHistoryEntry.tsx +28 -7
- package/src/components/history/EntityHistoryView.tsx +29 -24
- package/src/components/history/LastEditedByIndicator.tsx +4 -3
- package/src/components/index.ts +2 -0
- package/src/data_import/utils/get_import_inference_type.ts +6 -0
- package/src/form/EntityForm.tsx +267 -179
- package/src/form/EntityFormActions.tsx +50 -99
- package/src/form/EntityFormBinding.tsx +4 -2
- package/src/form/PropertyFieldBinding.tsx +4 -0
- package/src/form/components/FieldBlock.tsx +119 -0
- package/src/form/components/FormRail.tsx +125 -0
- package/src/form/components/FormSections.tsx +118 -0
- package/src/form/components/index.tsx +3 -2
- package/src/form/components/useRailVisible.tsx +46 -0
- package/src/form/field_bindings/BinaryFieldBinding.tsx +3 -2
- package/src/form/field_bindings/DateTimeFieldBinding.tsx +3 -2
- package/src/form/field_bindings/GeopointFieldBinding.tsx +3 -2
- package/src/form/field_bindings/MapFieldBinding.tsx +1 -2
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +3 -2
- package/src/form/field_bindings/MultiSelectFieldBinding.tsx +2 -1
- package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +2 -1
- package/src/form/field_bindings/ReferenceFieldBinding.tsx +2 -1
- package/src/form/field_bindings/RelationFieldBinding.tsx +6 -4
- package/src/form/field_bindings/RepeatFieldBinding.tsx +4 -1
- package/src/form/field_bindings/SelectFieldBinding.tsx +3 -2
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +31 -8
- package/src/form/field_bindings/SwitchFieldBinding.tsx +7 -3
- package/src/form/field_bindings/TextFieldBinding.tsx +18 -16
- package/src/form/field_bindings/UserSelectFieldBinding.tsx +3 -2
- package/src/form/field_bindings/VectorFieldBinding.tsx +2 -1
- package/src/hooks/navigation/useBuildUrlController.tsx +1 -1
- package/src/hooks/navigation/useTopLevelNavigation.ts +18 -7
- package/src/hooks/navigation/utils.ts +20 -0
- package/src/hooks/useBuildSideDialogsController.tsx +2 -2
- package/src/hooks/useBuildSidePanel.tsx +22 -61
- package/src/hooks/useEntityDisplayTitle.tsx +60 -0
- package/src/hooks/useHistory.ts +20 -10
- package/src/hooks/useRecordActions.tsx +69 -0
- package/src/hooks/useResolvedUsers.ts +10 -5
- package/src/preview/PropertyPreview.tsx +48 -22
- package/src/preview/components/InlineEntityListPreview.tsx +42 -0
- package/src/preview/components/ReferencePreview.tsx +34 -14
- package/src/preview/components/RelationPreview.tsx +34 -14
- package/src/preview/index.ts +1 -0
- package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +24 -1
- package/src/preview/property_previews/ArrayOfRelationsPreview.tsx +25 -1
- package/src/routes/RebaseRoute.tsx +2 -2
- package/src/types/components/EntityFormActionsProps.tsx +0 -1
- package/src/types/components/EntityFormProps.tsx +0 -6
- package/src/types/fields.tsx +27 -0
- package/dist/form/components/FormEntry.d.ts +0 -6
- package/dist/form/components/FormLayout.d.ts +0 -5
- package/dist/history-g9688IaK.js.map +0 -1
- package/dist/util-B5fJm1FA.js.map +0 -1
- package/src/form/components/FormEntry.tsx +0 -22
- package/src/form/components/FormLayout.tsx +0 -16
|
@@ -52,6 +52,7 @@ export function BinaryFieldBinding({
|
|
|
52
52
|
autoFocus,
|
|
53
53
|
property,
|
|
54
54
|
includeDescription,
|
|
55
|
+
hideLabel,
|
|
55
56
|
size = "large"
|
|
56
57
|
}: FieldProps<BinaryProperty>) {
|
|
57
58
|
|
|
@@ -87,11 +88,11 @@ export function BinaryFieldBinding({
|
|
|
87
88
|
return (
|
|
88
89
|
<div className="flex flex-col gap-2 w-full mt-2">
|
|
89
90
|
<div className="flex items-center justify-between mb-1">
|
|
90
|
-
<LabelWithIcon
|
|
91
|
+
{!hideLabel && <LabelWithIcon
|
|
91
92
|
icon={getIconForProperty(property, "small")}
|
|
92
93
|
required={property.validation?.required}
|
|
93
94
|
title={property.name ?? propertyKey}
|
|
94
|
-
/>
|
|
95
|
+
/>}
|
|
95
96
|
</div>
|
|
96
97
|
|
|
97
98
|
<PropertyIdCopyTooltip propertyKey={propertyKey}>
|
|
@@ -31,7 +31,8 @@ export function DateTimeFieldBinding({
|
|
|
31
31
|
disabled,
|
|
32
32
|
touched,
|
|
33
33
|
property,
|
|
34
|
-
includeDescription
|
|
34
|
+
includeDescription,
|
|
35
|
+
hideLabel
|
|
35
36
|
}: DateTimeFieldProps) {
|
|
36
37
|
|
|
37
38
|
const { locale } = useCustomizationController();
|
|
@@ -54,7 +55,7 @@ export function DateTimeFieldBinding({
|
|
|
54
55
|
locale={locale}
|
|
55
56
|
error={showError}
|
|
56
57
|
disabled={disabled}
|
|
57
|
-
label={<LabelWithIcon
|
|
58
|
+
label={hideLabel ? undefined : <LabelWithIcon
|
|
58
59
|
icon={getIconForProperty(property, "small")}
|
|
59
60
|
required={property.validation?.required}
|
|
60
61
|
className={showError ? "text-red-500 dark:text-red-500" : "text-text-secondary dark:text-text-secondary-dark"}
|
|
@@ -62,6 +62,7 @@ export function GeopointFieldBinding({
|
|
|
62
62
|
autoFocus,
|
|
63
63
|
property,
|
|
64
64
|
includeDescription,
|
|
65
|
+
hideLabel,
|
|
65
66
|
size = "large"
|
|
66
67
|
}: FieldProps<GeopointProperty>) {
|
|
67
68
|
|
|
@@ -129,11 +130,11 @@ export function GeopointFieldBinding({
|
|
|
129
130
|
return (
|
|
130
131
|
<div className="flex flex-col gap-2 w-full mt-2">
|
|
131
132
|
<div className="flex items-center justify-between mb-1">
|
|
132
|
-
<LabelWithIcon
|
|
133
|
+
{!hideLabel && <LabelWithIcon
|
|
133
134
|
icon={getIconForProperty(property, "small")}
|
|
134
135
|
required={property.validation?.required}
|
|
135
136
|
title={property.name ?? propertyKey}
|
|
136
|
-
/>
|
|
137
|
+
/>}
|
|
137
138
|
{!disabled && (latText || lngText) && (
|
|
138
139
|
<IconButton
|
|
139
140
|
size="small"
|
|
@@ -46,7 +46,7 @@ export function MapFieldBinding({
|
|
|
46
46
|
|
|
47
47
|
const mapFormView = <>
|
|
48
48
|
<div
|
|
49
|
-
className={
|
|
49
|
+
className={"py-1 flex flex-col space-y-2"}>
|
|
50
50
|
{Object.entries(mapProperties)
|
|
51
51
|
.filter(([_, property]) => !isHidden(property))
|
|
52
52
|
.map(([entryKey, childProperty], index) => {
|
|
@@ -96,7 +96,6 @@ export function MapFieldBinding({
|
|
|
96
96
|
expanded }
|
|
97
97
|
});
|
|
98
98
|
}}
|
|
99
|
-
className={property.admin?.widthPercentage !== undefined ? "mt-8" : undefined}
|
|
100
99
|
innerClassName={"px-2 md:px-4 pb-2 md:pb-4 pt-1 md:pt-2 bg-white dark:bg-surface-900"}
|
|
101
100
|
title={<LabelWithIconAndTooltip
|
|
102
101
|
propertyKey={propertyKey}
|
|
@@ -74,6 +74,7 @@ export function MarkdownEditorFieldBinding({
|
|
|
74
74
|
value,
|
|
75
75
|
setValue,
|
|
76
76
|
includeDescription,
|
|
77
|
+
hideLabel,
|
|
77
78
|
showError,
|
|
78
79
|
error,
|
|
79
80
|
minimalistView,
|
|
@@ -216,12 +217,12 @@ export function MarkdownEditorFieldBinding({
|
|
|
216
217
|
return (
|
|
217
218
|
<>
|
|
218
219
|
<div className="flex items-center w-full">
|
|
219
|
-
<LabelWithIconAndTooltip
|
|
220
|
+
{!hideLabel && <LabelWithIconAndTooltip
|
|
220
221
|
propertyKey={propertyKey}
|
|
221
222
|
icon={getIconForProperty(property, "small")}
|
|
222
223
|
required={property.validation?.required}
|
|
223
224
|
title={property.name ?? propertyKey}
|
|
224
|
-
className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
|
|
225
|
+
className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>}
|
|
225
226
|
<div className="flex-grow"/>
|
|
226
227
|
{property.admin?.clearable && !disabled && (
|
|
227
228
|
<IconButton
|
|
@@ -27,6 +27,7 @@ export function MultiSelectFieldBinding({
|
|
|
27
27
|
disabled,
|
|
28
28
|
property,
|
|
29
29
|
includeDescription,
|
|
30
|
+
hideLabel,
|
|
30
31
|
size = "large",
|
|
31
32
|
autoFocus
|
|
32
33
|
}: FieldProps<ArrayProperty, unknown, Record<string, unknown>>) {
|
|
@@ -91,7 +92,7 @@ export function MultiSelectFieldBinding({
|
|
|
91
92
|
value={validValue ? value.map((v) => v?.toString()) : []}
|
|
92
93
|
disabled={disabled}
|
|
93
94
|
modalPopover={true}
|
|
94
|
-
label={<LabelWithIconAndTooltip
|
|
95
|
+
label={hideLabel ? undefined : <LabelWithIconAndTooltip
|
|
95
96
|
propertyKey={propertyKey}
|
|
96
97
|
icon={getIconForProperty(property, "small")}
|
|
97
98
|
required={property.validation?.required}
|
|
@@ -27,6 +27,7 @@ export function ReadOnlyFieldBinding({
|
|
|
27
27
|
minimalistView,
|
|
28
28
|
property,
|
|
29
29
|
includeDescription,
|
|
30
|
+
hideLabel,
|
|
30
31
|
context
|
|
31
32
|
}: FieldProps<Property>) {
|
|
32
33
|
|
|
@@ -39,7 +40,7 @@ export function ReadOnlyFieldBinding({
|
|
|
39
40
|
|
|
40
41
|
<>
|
|
41
42
|
|
|
42
|
-
{!minimalistView && <LabelWithIconAndTooltip
|
|
43
|
+
{!minimalistView && !hideLabel && <LabelWithIconAndTooltip
|
|
43
44
|
propertyKey={propertyKey}
|
|
44
45
|
icon={getIconForProperty(property, "small")}
|
|
45
46
|
required={property.validation?.required}
|
|
@@ -49,6 +49,7 @@ function ReferenceFieldBindingInternal({
|
|
|
49
49
|
autoFocus,
|
|
50
50
|
property,
|
|
51
51
|
includeDescription,
|
|
52
|
+
hideLabel,
|
|
52
53
|
size = "medium"
|
|
53
54
|
}: FieldProps<ReferenceProperty>) {
|
|
54
55
|
if (!property.path) {
|
|
@@ -96,7 +97,7 @@ function ReferenceFieldBindingInternal({
|
|
|
96
97
|
|
|
97
98
|
return (
|
|
98
99
|
<>
|
|
99
|
-
{!minimalistView && <LabelWithIconAndTooltip
|
|
100
|
+
{!minimalistView && !hideLabel && <LabelWithIconAndTooltip
|
|
100
101
|
propertyKey={propertyKey}
|
|
101
102
|
icon={getIconForProperty(property, "small")}
|
|
102
103
|
required={property.validation?.required}
|
|
@@ -63,6 +63,7 @@ function RelationSelectorBinding({
|
|
|
63
63
|
isSubmitting,
|
|
64
64
|
property,
|
|
65
65
|
includeDescription,
|
|
66
|
+
hideLabel,
|
|
66
67
|
setValue,
|
|
67
68
|
relation,
|
|
68
69
|
manyRelation
|
|
@@ -75,12 +76,12 @@ function RelationSelectorBinding({
|
|
|
75
76
|
|
|
76
77
|
return (
|
|
77
78
|
<div className="">
|
|
78
|
-
<LabelWithIconAndTooltip
|
|
79
|
+
{!hideLabel && <LabelWithIconAndTooltip
|
|
79
80
|
propertyKey={propertyKey}
|
|
80
81
|
icon={getIconForProperty(property, "small")}
|
|
81
82
|
required={property.validation?.required}
|
|
82
83
|
title={property.name ?? propertyKey}
|
|
83
|
-
className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
|
|
84
|
+
className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>}
|
|
84
85
|
|
|
85
86
|
<RelationSelector
|
|
86
87
|
relation={relation}
|
|
@@ -116,6 +117,7 @@ function SingleRelationFieldBinding({
|
|
|
116
117
|
isSubmitting,
|
|
117
118
|
property,
|
|
118
119
|
includeDescription,
|
|
120
|
+
hideLabel,
|
|
119
121
|
setValue,
|
|
120
122
|
relation
|
|
121
123
|
}: FieldProps<RelationProperty> & { relation: Relation | undefined }) {
|
|
@@ -150,12 +152,12 @@ function SingleRelationFieldBinding({
|
|
|
150
152
|
|
|
151
153
|
return (
|
|
152
154
|
<>
|
|
153
|
-
<LabelWithIconAndTooltip
|
|
155
|
+
{!hideLabel && <LabelWithIconAndTooltip
|
|
154
156
|
propertyKey={propertyKey}
|
|
155
157
|
icon={getIconForProperty(property, "small")}
|
|
156
158
|
required={property.validation?.required}
|
|
157
159
|
title={property.name ?? propertyKey}
|
|
158
|
-
className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
|
|
160
|
+
className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>}
|
|
159
161
|
|
|
160
162
|
{!collection && <ErrorView
|
|
161
163
|
error={"The specified collection does not exist. Check console"}/>}
|
|
@@ -85,6 +85,10 @@ export function RepeatFieldBinding({
|
|
|
85
85
|
context,
|
|
86
86
|
partOfArray: true,
|
|
87
87
|
minimalistView: false,
|
|
88
|
+
// The panel header already names the field; repeating "Locale" on
|
|
89
|
+
// every row of a three-item array is noise, and the label was what
|
|
90
|
+
// made each row a 76px card around a two-character value.
|
|
91
|
+
hideLabel: true,
|
|
88
92
|
autoFocus: internalId === lastAddedId
|
|
89
93
|
};
|
|
90
94
|
return <ErrorBoundary>
|
|
@@ -104,7 +108,6 @@ export function RepeatFieldBinding({
|
|
|
104
108
|
sortable={sortable}
|
|
105
109
|
newDefaultEntry={getDefaultValueFor(property.of)}
|
|
106
110
|
onValueChange={(value) => setFieldValue(propertyKey, value)}
|
|
107
|
-
className={property.admin?.widthPercentage !== undefined ? "mt-8" : undefined}
|
|
108
111
|
/>;
|
|
109
112
|
|
|
110
113
|
const title = (<>
|
|
@@ -31,6 +31,7 @@ export function SelectFieldBinding({
|
|
|
31
31
|
touched,
|
|
32
32
|
property,
|
|
33
33
|
includeDescription,
|
|
34
|
+
hideLabel,
|
|
34
35
|
size = "large"
|
|
35
36
|
}: FieldProps<StringProperty | NumberProperty>) {
|
|
36
37
|
|
|
@@ -58,7 +59,7 @@ export function SelectFieldBinding({
|
|
|
58
59
|
fullWidth={true}
|
|
59
60
|
position="item-aligned"
|
|
60
61
|
inputClassName={cls("w-full")}
|
|
61
|
-
label={
|
|
62
|
+
label={hideLabel ? undefined : (
|
|
62
63
|
<PropertyIdCopyTooltip propertyKey={propertyKey}>
|
|
63
64
|
<LabelWithIcon
|
|
64
65
|
icon={getIconForProperty(property, "small")}
|
|
@@ -66,7 +67,7 @@ export function SelectFieldBinding({
|
|
|
66
67
|
title={property.name ?? propertyKey}
|
|
67
68
|
className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5 my-0"}
|
|
68
69
|
/>
|
|
69
|
-
</PropertyIdCopyTooltip>}
|
|
70
|
+
</PropertyIdCopyTooltip>)}
|
|
70
71
|
endAdornment={
|
|
71
72
|
property.admin?.clearable && !disabled && <IconButton
|
|
72
73
|
size="small"
|
|
@@ -41,7 +41,15 @@ import {
|
|
|
41
41
|
} from "@rebasepro/ui";
|
|
42
42
|
import { useClearRestoreValue } from "../useClearRestoreValue";
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
// Height comes from the thumbnails now. It used to be a flat `min-h-[254px]`
|
|
45
|
+
// on top of another 250px inside, so a field holding one small image
|
|
46
|
+
// reserved close to 300px of the form for mostly empty space.
|
|
47
|
+
// One fixed height for the whole zone — 126px of preview row, 34px of hint,
|
|
48
|
+
// and the padding between. Pinned on the root rather than on the children
|
|
49
|
+
// because the hint reflows once files exist ("Drag to reorder"), and any
|
|
50
|
+
// content-driven height makes a filled field taller than the same field
|
|
51
|
+
// empty. Extra thumbnails scroll horizontally instead of growing it.
|
|
52
|
+
const dropZoneClasses = "box-border relative pt-[2px] h-[172px] items-center border border-transparent outline-none rounded-md duration-200 ease-[cubic-bezier(0.4,0,0.2,1)] focus:border-primary-solid";
|
|
45
53
|
const disabledClasses = fieldBackgroundDisabledMixin;
|
|
46
54
|
const nonActiveDropClasses = fieldBackgroundHoverMixin
|
|
47
55
|
const activeDropClasses = "pt-0 border-2 border-solid"
|
|
@@ -58,6 +66,7 @@ export function StorageUploadFieldBinding({
|
|
|
58
66
|
minimalistView,
|
|
59
67
|
property,
|
|
60
68
|
includeDescription,
|
|
69
|
+
hideLabel,
|
|
61
70
|
context,
|
|
62
71
|
isSubmitting
|
|
63
72
|
}: FieldProps<StringProperty | ArrayProperty>) {
|
|
@@ -98,7 +107,7 @@ export function StorageUploadFieldBinding({
|
|
|
98
107
|
|
|
99
108
|
<>
|
|
100
109
|
|
|
101
|
-
{!minimalistView &&
|
|
110
|
+
{!minimalistView && !hideLabel &&
|
|
102
111
|
<LabelWithIconAndTooltip
|
|
103
112
|
propertyKey={propertyKey}
|
|
104
113
|
icon={getIconForProperty(property, "small")}
|
|
@@ -214,7 +223,12 @@ function SortableStorageItem({
|
|
|
214
223
|
style={style}
|
|
215
224
|
{...attributes}
|
|
216
225
|
{...listeners}
|
|
217
|
-
|
|
226
|
+
// No vertical margin: the strip already pads itself, and `m-1` made
|
|
227
|
+
// each item 8px taller than the row's content box — enough to make a
|
|
228
|
+
// field holding one image scroll vertically behind a hidden
|
|
229
|
+
// scrollbar. `shrink-0` keeps thumbnails square once there are more
|
|
230
|
+
// of them than fit across.
|
|
231
|
+
className={cls("rounded-md shrink-0")}
|
|
218
232
|
tabIndex={-1}
|
|
219
233
|
>
|
|
220
234
|
{child}
|
|
@@ -310,9 +324,15 @@ function FileDropComponent({
|
|
|
310
324
|
})}
|
|
311
325
|
>
|
|
312
326
|
<div
|
|
313
|
-
className={cls("flex items-center p-1 px-
|
|
314
|
-
|
|
315
|
-
|
|
327
|
+
className={cls("flex items-center gap-2 p-1 px-3 no-scrollbar",
|
|
328
|
+
// Horizontal only. `overflow-auto` scrolls both axes, so any
|
|
329
|
+
// pixel of vertical overflow turned the field into a
|
|
330
|
+
// scrollable box with nothing visible to scroll to.
|
|
331
|
+
multipleFilesSupported && internalValue.length ? "overflow-x-auto overflow-y-hidden" : "",
|
|
332
|
+
// A fixed height, not a minimum: the 118px preview overflowed
|
|
333
|
+
// a `min-h`, so a field with a file stood taller than the same
|
|
334
|
+
// field empty. 126px is the preview plus its padding.
|
|
335
|
+
"h-[126px]"
|
|
316
336
|
)}
|
|
317
337
|
>
|
|
318
338
|
<input
|
|
@@ -339,9 +359,12 @@ function FileDropComponent({
|
|
|
339
359
|
</div>
|
|
340
360
|
|
|
341
361
|
<div
|
|
342
|
-
|
|
362
|
+
// Two lines' worth, fixed: the hint gains "Drag to reorder" once
|
|
363
|
+
// the field holds something, and a reflow there put the filled
|
|
364
|
+
// state 25px taller than the empty one.
|
|
365
|
+
className="box-border mx-3 mb-2.5 h-[34px] flex items-center justify-center text-center">
|
|
343
366
|
<Typography align={"center"}
|
|
344
|
-
variant={"
|
|
367
|
+
variant={"caption"}
|
|
345
368
|
className={disabled ? "text-surface-accent-600 dark:text-surface-accent-500" : ""}>
|
|
346
369
|
{helpText}
|
|
347
370
|
</Typography>
|
|
@@ -27,7 +27,8 @@ export const SwitchFieldBinding = function SwitchFieldBinding({
|
|
|
27
27
|
disabled,
|
|
28
28
|
size = "large",
|
|
29
29
|
property,
|
|
30
|
-
includeDescription
|
|
30
|
+
includeDescription,
|
|
31
|
+
hideLabel
|
|
31
32
|
}: FieldProps<BooleanProperty>) {
|
|
32
33
|
|
|
33
34
|
useClearRestoreValue({
|
|
@@ -44,8 +45,11 @@ export const SwitchFieldBinding = function SwitchFieldBinding({
|
|
|
44
45
|
value={value as boolean | null}
|
|
45
46
|
onValueChange={(v) => setValue(v)}
|
|
46
47
|
error={showError}
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
// The control is `justify-between`, so with the label lifted
|
|
49
|
+
// out the switch would drift to the far edge of an otherwise
|
|
50
|
+
// empty box. Anchor it to the start instead.
|
|
51
|
+
position={hideLabel ? "start" : undefined}
|
|
52
|
+
label={hideLabel ? undefined : <LabelWithIcon
|
|
49
53
|
icon={getIconForProperty(property, "small")}
|
|
50
54
|
required={property.validation?.required}
|
|
51
55
|
title={property.name ?? propertyKey}/>}
|
|
@@ -36,6 +36,7 @@ export function TextFieldBinding<T extends string | number>({
|
|
|
36
36
|
autoFocus,
|
|
37
37
|
property,
|
|
38
38
|
includeDescription,
|
|
39
|
+
hideLabel,
|
|
39
40
|
size = "large"
|
|
40
41
|
}: FieldProps<StringProperty | NumberProperty>) {
|
|
41
42
|
|
|
@@ -85,12 +86,17 @@ export function TextFieldBinding<T extends string | number>({
|
|
|
85
86
|
else if (property.admin?.urlPreview) inputType = "url";
|
|
86
87
|
}
|
|
87
88
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
89
|
+
// `undefined` rather than an empty element: TextField and the multiline box
|
|
90
|
+
// both reserve a label row whenever `label` is truthy, so a null-rendering
|
|
91
|
+
// element would leave the gap behind without the text.
|
|
92
|
+
const label = hideLabel
|
|
93
|
+
? undefined
|
|
94
|
+
: (
|
|
95
|
+
<LabelWithIcon
|
|
96
|
+
icon={getIconForProperty(property, "small")}
|
|
97
|
+
required={property.validation?.required || property.isId === true}
|
|
98
|
+
title={property.name ?? propertyKey}/>
|
|
99
|
+
);
|
|
94
100
|
return (<>
|
|
95
101
|
<PropertyIdCopyTooltip propertyKey={propertyKey}>
|
|
96
102
|
{isMultiline ? (
|
|
@@ -98,20 +104,20 @@ export function TextFieldBinding<T extends string | number>({
|
|
|
98
104
|
"rounded-md relative max-w-full min-h-[64px]",
|
|
99
105
|
fieldBackgroundMixin,
|
|
100
106
|
fieldBackgroundHoverMixin,
|
|
101
|
-
showError && error ? "border border-red-500 dark:border-red-600" : ""
|
|
102
|
-
property.admin?.widthPercentage !== undefined ? "mt-8" : undefined
|
|
107
|
+
showError && error ? "border border-red-500 dark:border-red-600" : ""
|
|
103
108
|
)}>
|
|
104
|
-
<div
|
|
109
|
+
{label && <div
|
|
105
110
|
className="pointer-events-none absolute top-1 text-xs font-medium px-3 text-text-secondary dark:text-text-secondary-dark">
|
|
106
111
|
{label}
|
|
107
|
-
</div>
|
|
112
|
+
</div>}
|
|
108
113
|
<TextareaAutosize
|
|
109
114
|
value={displayValue}
|
|
110
115
|
onChange={onChange}
|
|
111
116
|
autoFocus={autoFocus}
|
|
112
117
|
disabled={disabled}
|
|
113
118
|
className={cls(
|
|
114
|
-
"rounded-md resize-none w-full outline-none
|
|
119
|
+
"rounded-md resize-none w-full outline-none text-base bg-transparent min-h-[64px] px-3",
|
|
120
|
+
label ? "pt-8 pb-2" : "py-2",
|
|
115
121
|
disabled && "outline-none opacity-50 text-surface-accent-600 dark:text-surface-accent-500",
|
|
116
122
|
showError && error ? "text-red-500 dark:text-red-600" : ""
|
|
117
123
|
)}
|
|
@@ -131,11 +137,7 @@ export function TextFieldBinding<T extends string | number>({
|
|
|
131
137
|
value={displayValue}
|
|
132
138
|
onChange={onChange}
|
|
133
139
|
autoFocus={autoFocus}
|
|
134
|
-
|
|
135
|
-
label={<LabelWithIcon
|
|
136
|
-
icon={getIconForProperty(property, "small")}
|
|
137
|
-
required={property.validation?.required || property.isId === true}
|
|
138
|
-
title={property.name ?? propertyKey}/>}
|
|
140
|
+
label={label}
|
|
139
141
|
type={inputType}
|
|
140
142
|
disabled={disabled}
|
|
141
143
|
endAdornment={
|
|
@@ -30,6 +30,7 @@ export function UserSelectFieldBinding({
|
|
|
30
30
|
touched,
|
|
31
31
|
property,
|
|
32
32
|
includeDescription,
|
|
33
|
+
hideLabel,
|
|
33
34
|
size = "large"
|
|
34
35
|
}: UserSelectProps) {
|
|
35
36
|
|
|
@@ -37,14 +38,14 @@ export function UserSelectFieldBinding({
|
|
|
37
38
|
|
|
38
39
|
return (
|
|
39
40
|
<>
|
|
40
|
-
<PropertyIdCopyTooltip propertyKey={propertyKey}>
|
|
41
|
+
{!hideLabel && <PropertyIdCopyTooltip propertyKey={propertyKey}>
|
|
41
42
|
<LabelWithIcon
|
|
42
43
|
icon={getIconForProperty(property, "small")}
|
|
43
44
|
required={property.validation?.required}
|
|
44
45
|
title={property.name}
|
|
45
46
|
className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5 my-0"}
|
|
46
47
|
/>
|
|
47
|
-
</PropertyIdCopyTooltip>
|
|
48
|
+
</PropertyIdCopyTooltip>}
|
|
48
49
|
|
|
49
50
|
<UserSelector
|
|
50
51
|
value={value as string | null | undefined}
|
|
@@ -37,6 +37,7 @@ export function VectorFieldBinding({
|
|
|
37
37
|
autoFocus,
|
|
38
38
|
property,
|
|
39
39
|
includeDescription,
|
|
40
|
+
hideLabel,
|
|
40
41
|
size = "large"
|
|
41
42
|
}: FieldProps<VectorProperty>) {
|
|
42
43
|
const isVectorObject = (val: unknown): val is { value: number[] } => {
|
|
@@ -86,7 +87,7 @@ export function VectorFieldBinding({
|
|
|
86
87
|
});
|
|
87
88
|
};
|
|
88
89
|
|
|
89
|
-
const label = (
|
|
90
|
+
const label = hideLabel ? null : (
|
|
90
91
|
<LabelWithIcon
|
|
91
92
|
icon={getIconForProperty(property, "small")}
|
|
92
93
|
required={property.validation?.required}
|
|
@@ -2,7 +2,7 @@ import type { UrlController, NavigateOptions } from "@rebasepro/admin-types";
|
|
|
2
2
|
import { useCallback, useMemo } from "react";
|
|
3
3
|
import { removeInitialAndTrailingSlashes, resolveCollectionPathIds } from "@rebasepro/app";
|
|
4
4
|
import { CollectionRegistryController } from "@rebasepro/types";
|
|
5
|
-
import { useNavigate } from "react-router
|
|
5
|
+
import { useNavigate } from "react-router";
|
|
6
6
|
|
|
7
7
|
export function useBuildUrlController(props: {
|
|
8
8
|
basePath: string,
|
|
@@ -6,7 +6,7 @@ import { deepEqual as equal } from "fast-equals";
|
|
|
6
6
|
import { CollectionRegistryController } from "@rebasepro/types";
|
|
7
7
|
import { CollectionRegistry } from "@rebasepro/common";
|
|
8
8
|
|
|
9
|
-
import { computeNavigationGroups, getGroup, NAVIGATION_ADMIN_GROUP_NAME, NAVIGATION_DEFAULT_GROUP_NAME } from "./utils";
|
|
9
|
+
import { computeNavigationGroups, getGroup, isBottomPinnedGroupName, NAVIGATION_ADMIN_GROUP_NAME, NAVIGATION_DEFAULT_GROUP_NAME } from "./utils";
|
|
10
10
|
|
|
11
11
|
export type UseTopLevelNavigationProps = {
|
|
12
12
|
collections: AdminCollection[];
|
|
@@ -178,10 +178,18 @@ export function useTopLevelNavigation(
|
|
|
178
178
|
}, [] as NavigationEntry[])
|
|
179
179
|
];
|
|
180
180
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
181
|
+
// Groups that sink to the bottom. Two sources, because the string
|
|
182
|
+
// comparison predates the flag and apps depend on it: the names in
|
|
183
|
+
// `NAVIGATION_BOTTOM_GROUP_NAMES`, and any group holding a view that
|
|
184
|
+
// asked for it — which is the only one of the two that survives the
|
|
185
|
+
// group being renamed or translated.
|
|
186
|
+
const pinnedGroups = new Set<string>();
|
|
187
|
+
for (const view of [...(views ?? []), ...(adminViews ?? [])]) {
|
|
188
|
+
if (view.pinToBottom) pinnedGroups.add(getGroup(view));
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const groupOrderValue = (groupName?: string): number =>
|
|
192
|
+
(isBottomPinnedGroupName(groupName) || (groupName !== undefined && pinnedGroups.has(groupName))) ? 1 : 0;
|
|
185
193
|
|
|
186
194
|
const usedViewsOrder = viewsOrder ?? navigationEntriesOrder;
|
|
187
195
|
navigationEntries = navigationEntries.sort((a, b) => {
|
|
@@ -218,8 +226,11 @@ export function useTopLevelNavigation(
|
|
|
218
226
|
];
|
|
219
227
|
|
|
220
228
|
const uniqueGroupsArray = [...new Set(allDefinedGroups)];
|
|
221
|
-
|
|
222
|
-
|
|
229
|
+
// Same rule the entry sort uses — read through `groupOrderValue` rather
|
|
230
|
+
// than repeated inline, so the drawer's group order and the entries
|
|
231
|
+
// inside it cannot disagree about which groups are last.
|
|
232
|
+
const lastGroups = uniqueGroupsArray.filter(g => groupOrderValue(g) === 1);
|
|
233
|
+
const otherGroups = uniqueGroupsArray.filter(g => groupOrderValue(g) === 0);
|
|
223
234
|
const uniqueGroups = [...otherGroups, ...lastGroups] as string[];
|
|
224
235
|
|
|
225
236
|
const computedTopLevelNav = {
|
|
@@ -7,6 +7,26 @@ import { deepEqual as equal } from "fast-equals";
|
|
|
7
7
|
export const NAVIGATION_DEFAULT_GROUP_NAME = "Views";
|
|
8
8
|
export const NAVIGATION_ADMIN_GROUP_NAME = "Admin";
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Group names that sink to the bottom of the drawer on their name alone.
|
|
12
|
+
*
|
|
13
|
+
* A magic string, and it stays one for compatibility: apps have been relying on
|
|
14
|
+
* `group: "Settings"` landing last since before there was a flag, and taking it
|
|
15
|
+
* away would silently reshuffle their navigation.
|
|
16
|
+
*
|
|
17
|
+
* It is a bad way to ask for the behaviour, though — it is invisible from the
|
|
18
|
+
* `group?: string` type, and it is defeated by the most ordinary edit there is:
|
|
19
|
+
* translating the label. `group: "Ajustes"` is the same group to a reader and a
|
|
20
|
+
* different one to this comparison, so the ordering just quietly stops
|
|
21
|
+
* happening. Set {@link AppView.pinToBottom} instead, which says so.
|
|
22
|
+
*/
|
|
23
|
+
export const NAVIGATION_BOTTOM_GROUP_NAMES = ["Admin", "Settings"] as const;
|
|
24
|
+
|
|
25
|
+
/** Whether a group sinks to the bottom by virtue of its name. @see NAVIGATION_BOTTOM_GROUP_NAMES */
|
|
26
|
+
export function isBottomPinnedGroupName(groupName?: string): boolean {
|
|
27
|
+
return groupName !== undefined && (NAVIGATION_BOTTOM_GROUP_NAMES as readonly string[]).includes(groupName);
|
|
28
|
+
}
|
|
29
|
+
|
|
10
30
|
export function getGroup(collectionOrView: AdminCollection | AppView) {
|
|
11
31
|
const trimmed = collectionOrView.group?.trim();
|
|
12
32
|
if (!trimmed || trimmed === "") {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { SideDialogPanelProps, SideDialogsController } from "../hooks/useSideDialogsController";
|
|
2
2
|
import { useCallback, useEffect, useRef, useState, useMemo } from "react";
|
|
3
|
-
import { useLocation, useNavigate } from "react-router
|
|
3
|
+
import { useLocation, useNavigate } from "react-router";
|
|
4
4
|
;
|
|
5
5
|
import { deepEqual as equal } from "fast-equals"
|
|
6
|
-
import { Location } from "react-router
|
|
6
|
+
import { Location } from "react-router";
|
|
7
7
|
|
|
8
8
|
interface SideDialogLocationState {
|
|
9
9
|
base_location?: Location;
|