@firecms/core 3.0.0-beta.8 → 3.0.0-beta.9

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 (190) hide show
  1. package/dist/app/Drawer.d.ts +1 -1
  2. package/dist/app/Scaffold.d.ts +1 -1
  3. package/dist/components/ArrayContainer.d.ts +2 -1
  4. package/dist/components/CircularProgressCenter.d.ts +1 -1
  5. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +0 -1
  6. package/dist/components/EntityCollectionTable/fields/TableReferenceField.d.ts +1 -1
  7. package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +1 -1
  8. package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +1 -1
  9. package/dist/components/EntityPreview.d.ts +1 -1
  10. package/dist/components/ErrorView.d.ts +1 -1
  11. package/dist/components/HomePage/DefaultHomePage.d.ts +1 -1
  12. package/dist/components/HomePage/NavigationCardBinding.d.ts +1 -1
  13. package/dist/components/PropertyIdCopyTooltip.d.ts +8 -0
  14. package/dist/components/VirtualTable/VirtualTableProps.d.ts +10 -6
  15. package/dist/components/common/useColumnsIds.d.ts +2 -1
  16. package/dist/components/index.d.ts +1 -0
  17. package/dist/core/DefaultAppBar.d.ts +1 -1
  18. package/dist/core/DefaultDrawer.d.ts +1 -1
  19. package/dist/core/DrawerNavigationItem.d.ts +2 -1
  20. package/dist/core/EntityEditView.d.ts +3 -3
  21. package/dist/core/FireCMS.d.ts +1 -1
  22. package/dist/core/NavigationRoutes.d.ts +1 -1
  23. package/dist/form/PropertyFieldBinding.d.ts +1 -1
  24. package/dist/form/components/FormikArrayContainer.d.ts +2 -1
  25. package/dist/form/components/LabelWithIcon.d.ts +1 -1
  26. package/dist/form/components/LabelWithIconAndTooltip.d.ts +15 -0
  27. package/dist/form/components/index.d.ts +1 -0
  28. package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +1 -1
  29. package/dist/form/field_bindings/ArrayOfReferencesFieldBinding.d.ts +1 -1
  30. package/dist/form/field_bindings/BlockFieldBinding.d.ts +1 -1
  31. package/dist/form/field_bindings/KeyValueFieldBinding.d.ts +1 -1
  32. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  33. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +11 -0
  34. package/dist/form/field_bindings/{MultiSelectBinding.d.ts → MultiSelectFieldBinding.d.ts} +1 -1
  35. package/dist/form/field_bindings/ReadOnlyFieldBinding.d.ts +1 -1
  36. package/dist/form/field_bindings/RepeatFieldBinding.d.ts +1 -1
  37. package/dist/form/field_bindings/SelectFieldBinding.d.ts +1 -1
  38. package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +1 -1
  39. package/dist/form/field_bindings/TextFieldBinding.d.ts +1 -1
  40. package/dist/form/index.d.ts +3 -3
  41. package/dist/form/useClearRestoreValue.d.ts +2 -2
  42. package/dist/hooks/useProjectLog.d.ts +2 -2
  43. package/dist/index.es.js +14127 -11014
  44. package/dist/index.es.js.map +1 -1
  45. package/dist/index.umd.js +19987 -587
  46. package/dist/index.umd.js.map +1 -1
  47. package/dist/preview/PropertyPreviewProps.d.ts +1 -1
  48. package/dist/preview/components/EnumValuesChip.d.ts +1 -1
  49. package/dist/preview/components/ReferencePreview.d.ts +1 -1
  50. package/dist/types/auth.d.ts +1 -1
  51. package/dist/types/collections.d.ts +12 -3
  52. package/dist/types/datasource.d.ts +35 -22
  53. package/dist/types/entities.d.ts +1 -0
  54. package/dist/types/entity_overrides.d.ts +2 -2
  55. package/dist/types/fields.d.ts +20 -15
  56. package/dist/types/navigation.d.ts +1 -0
  57. package/dist/types/properties.d.ts +18 -18
  58. package/dist/types/side_dialogs_controller.d.ts +10 -0
  59. package/dist/types/storage.d.ts +75 -0
  60. package/dist/util/entities.d.ts +1 -1
  61. package/dist/util/icon_list.d.ts +5 -1
  62. package/dist/util/icons.d.ts +1 -0
  63. package/dist/util/index.d.ts +1 -0
  64. package/dist/util/plurals.d.ts +0 -2
  65. package/dist/util/property_utils.d.ts +1 -1
  66. package/dist/util/resolutions.d.ts +15 -1
  67. package/dist/util/storage.d.ts +1 -1
  68. package/dist/util/useStorageUploadController.d.ts +2 -2
  69. package/package.json +15 -17
  70. package/src/app/Drawer.tsx +1 -1
  71. package/src/app/Scaffold.tsx +22 -27
  72. package/src/components/ArrayContainer.tsx +15 -10
  73. package/src/components/CircularProgressCenter.tsx +1 -1
  74. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +4 -9
  75. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +2 -2
  76. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +4 -2
  77. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +21 -14
  78. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +12 -4
  79. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +17 -19
  80. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +19 -7
  81. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +3 -5
  82. package/src/components/EntityCollectionView/EntityCollectionView.tsx +26 -25
  83. package/src/components/EntityCollectionView/useSelectionController.tsx +19 -7
  84. package/src/components/EntityPreview.tsx +30 -31
  85. package/src/components/ErrorView.tsx +1 -1
  86. package/src/components/HomePage/DefaultHomePage.tsx +24 -18
  87. package/src/components/HomePage/NavigationCardBinding.tsx +1 -1
  88. package/src/components/HomePage/SmallNavigationCard.tsx +1 -2
  89. package/src/components/PropertyIdCopyTooltip.tsx +48 -0
  90. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +7 -6
  91. package/src/components/SearchIconsView.tsx +5 -2
  92. package/src/components/SelectableTable/SelectableTable.tsx +2 -4
  93. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +1 -1
  94. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +54 -7
  95. package/src/components/VirtualTable/VirtualTable.tsx +33 -9
  96. package/src/components/VirtualTable/VirtualTableCell.tsx +1 -9
  97. package/src/components/VirtualTable/VirtualTableProps.tsx +12 -8
  98. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +3 -3
  99. package/src/components/VirtualTable/fields/VirtualTableInput.tsx +2 -1
  100. package/src/components/VirtualTable/fields/VirtualTableNumberInput.tsx +2 -1
  101. package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +14 -28
  102. package/src/components/common/useColumnsIds.tsx +13 -0
  103. package/src/components/common/useDataSourceEntityCollectionTableController.tsx +12 -12
  104. package/src/components/common/useTableSearchHelper.ts +1 -0
  105. package/src/components/index.tsx +1 -0
  106. package/src/core/DefaultAppBar.tsx +3 -3
  107. package/src/core/DefaultDrawer.tsx +18 -12
  108. package/src/core/DrawerNavigationItem.tsx +31 -27
  109. package/src/core/EntityEditView.tsx +136 -109
  110. package/src/core/FireCMS.tsx +2 -2
  111. package/src/core/NavigationRoutes.tsx +1 -1
  112. package/src/core/SideDialogs.tsx +1 -0
  113. package/src/core/field_configs.tsx +5 -5
  114. package/src/form/PropertyFieldBinding.tsx +24 -14
  115. package/src/form/components/CustomIdField.tsx +4 -2
  116. package/src/form/components/FieldHelperText.tsx +1 -1
  117. package/src/form/components/FormikArrayContainer.tsx +4 -1
  118. package/src/form/components/LabelWithIcon.tsx +27 -19
  119. package/src/form/components/LabelWithIconAndTooltip.tsx +28 -0
  120. package/src/form/components/StorageItemPreview.tsx +1 -0
  121. package/src/form/components/StorageUploadProgress.tsx +0 -1
  122. package/src/form/components/index.tsx +1 -0
  123. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +22 -14
  124. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +24 -22
  125. package/src/form/field_bindings/BlockFieldBinding.tsx +13 -11
  126. package/src/form/field_bindings/DateTimeFieldBinding.tsx +17 -14
  127. package/src/form/field_bindings/KeyValueFieldBinding.tsx +8 -7
  128. package/src/form/field_bindings/MapFieldBinding.tsx +16 -24
  129. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +150 -0
  130. package/src/form/field_bindings/{MultiSelectBinding.tsx → MultiSelectFieldBinding.tsx} +25 -20
  131. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +9 -7
  132. package/src/form/field_bindings/ReferenceFieldBinding.tsx +27 -18
  133. package/src/form/field_bindings/RepeatFieldBinding.tsx +27 -17
  134. package/src/form/field_bindings/SelectFieldBinding.tsx +17 -10
  135. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +36 -17
  136. package/src/form/field_bindings/SwitchFieldBinding.tsx +9 -5
  137. package/src/form/field_bindings/TextFieldBinding.tsx +26 -23
  138. package/src/form/index.tsx +4 -9
  139. package/src/form/useClearRestoreValue.tsx +2 -2
  140. package/src/hooks/data/delete.ts +2 -1
  141. package/src/hooks/data/save.ts +5 -2
  142. package/src/hooks/data/useDataSource.tsx +11 -3
  143. package/src/hooks/useBuildNavigationController.tsx +10 -3
  144. package/src/hooks/useProjectLog.tsx +18 -7
  145. package/src/internal/useBuildDataSource.ts +59 -76
  146. package/src/internal/useBuildSideDialogsController.tsx +1 -0
  147. package/src/internal/useBuildSideEntityController.tsx +17 -4
  148. package/src/internal/useUnsavedChangesDialog.tsx +3 -1
  149. package/src/preview/PropertyPreview.tsx +2 -2
  150. package/src/preview/PropertyPreviewProps.tsx +1 -1
  151. package/src/preview/components/BooleanPreview.tsx +1 -1
  152. package/src/preview/components/EnumValuesChip.tsx +1 -1
  153. package/src/preview/components/ImagePreview.tsx +4 -2
  154. package/src/preview/components/ReferencePreview.tsx +2 -13
  155. package/src/preview/components/UrlComponentPreview.tsx +1 -1
  156. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +1 -1
  157. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +1 -1
  158. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +1 -1
  159. package/src/preview/property_previews/ArrayOneOfPreview.tsx +2 -2
  160. package/src/preview/property_previews/ArrayPropertyPreview.tsx +1 -1
  161. package/src/preview/property_previews/MapPropertyPreview.tsx +1 -1
  162. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +2 -2
  163. package/src/preview/property_previews/StringPropertyPreview.tsx +2 -2
  164. package/src/preview/util.ts +2 -2
  165. package/src/types/auth.tsx +1 -1
  166. package/src/types/collections.ts +15 -4
  167. package/src/types/datasource.ts +42 -27
  168. package/src/types/entities.ts +2 -0
  169. package/src/types/entity_overrides.tsx +2 -2
  170. package/src/types/fields.tsx +23 -17
  171. package/src/types/navigation.ts +1 -0
  172. package/src/types/properties.ts +18 -17
  173. package/src/types/side_dialogs_controller.tsx +13 -0
  174. package/src/types/storage.ts +82 -0
  175. package/src/util/entities.ts +1 -1
  176. package/src/util/icon_list.ts +14 -9
  177. package/src/util/icons.tsx +8 -2
  178. package/src/util/index.ts +1 -0
  179. package/src/util/plurals.ts +0 -2
  180. package/src/util/property_utils.tsx +1 -1
  181. package/src/util/references.ts +3 -0
  182. package/src/util/resolutions.ts +43 -11
  183. package/src/util/storage.ts +6 -2
  184. package/src/util/useStorageUploadController.tsx +15 -7
  185. package/dist/components/PropertyIdCopyTooltipContent.d.ts +0 -3
  186. package/dist/form/PropertiesForm.d.ts +0 -8
  187. package/dist/form/field_bindings/MarkdownFieldBinding.d.ts +0 -9
  188. package/src/components/PropertyIdCopyTooltipContent.tsx +0 -27
  189. package/src/form/PropertiesForm.tsx +0 -81
  190. package/src/form/field_bindings/MarkdownFieldBinding.tsx +0 -695
@@ -1,7 +1,17 @@
1
1
  import React, { useState } from "react";
2
2
  import { EnumValuesChip } from "../../../preview";
3
3
  import { VirtualTableWhereFilterOp } from "../../VirtualTable";
4
- import { Checkbox, ClearIcon, IconButton, Label, Select, SelectItem, TextField } from "@firecms/ui";
4
+ import {
5
+ Checkbox,
6
+ ClearIcon,
7
+ IconButton,
8
+ Label,
9
+ MultiSelect,
10
+ MultiSelectItem,
11
+ Select,
12
+ SelectItem,
13
+ TextField
14
+ } from "@firecms/ui";
5
15
  import { EnumValueConfig } from "../../../types";
6
16
 
7
17
  interface StringNumberFilterFieldProps {
@@ -82,6 +92,7 @@ export function StringNumberFilterField({
82
92
  }
83
93
 
84
94
  const multiple = multipleSelectOperations.includes(operation);
95
+
85
96
  return (
86
97
 
87
98
  <div className="flex w-[440px]">
@@ -117,17 +128,14 @@ export function StringNumberFilterField({
117
128
  </IconButton>}
118
129
  />}
119
130
 
120
- {enumValues &&
131
+ {enumValues && !multiple &&
121
132
  <Select
122
133
  position={"item-aligned"}
123
- value={internalValue !== undefined
124
- ? (Array.isArray(internalValue) ? internalValue.map(e => String(e)) : String(internalValue))
125
- : isArray ? [] : ""}
134
+ value={typeof internalValue === "string" ? internalValue : ""}
126
135
  onValueChange={(value) => {
127
136
  if (value !== "")
128
137
  updateFilter(operation, dataType === "number" ? parseInt(value as string) : value as string)
129
138
  }}
130
- multiple={multiple}
131
139
  endAdornment={internalValue && <IconButton
132
140
  className="absolute right-2 top-3"
133
141
  onClick={(e) => updateFilter(operation, undefined)}>
@@ -136,6 +144,8 @@ export function StringNumberFilterField({
136
144
  renderValue={(enumKey) => {
137
145
  if (enumKey === null)
138
146
  return "Filter for null values";
147
+ if (enumKey === undefined)
148
+ return null;
139
149
 
140
150
  return <EnumValuesChip
141
151
  key={`select_value_${name}_${enumKey}`}
@@ -144,7 +154,7 @@ export function StringNumberFilterField({
144
154
  size={"small"}/>;
145
155
  }}>
146
156
  {enumValues.map((enumConfig) => (
147
- <SelectItem key={`select_value_${name}_${enumConfig.id}`}
157
+ <SelectItem key={`select_item_${name}_${enumConfig.id}`}
148
158
  value={String(enumConfig.id)}>
149
159
  <EnumValuesChip
150
160
  enumKey={String(enumConfig.id)}
@@ -155,6 +165,43 @@ export function StringNumberFilterField({
155
165
  </Select>
156
166
  }
157
167
 
168
+ {enumValues && multiple &&
169
+ <MultiSelect
170
+ position={"item-aligned"}
171
+ value={Array.isArray(internalValue) ? internalValue.map(e => String(e)) : []}
172
+ onValueChange={(value) => {
173
+ updateFilter(operation, dataType === "number" ? value.map(v => parseInt(v)) : value)
174
+ }}
175
+ multiple={multiple}
176
+ endAdornment={internalValue && <IconButton
177
+ className="absolute right-2 top-3"
178
+ onClick={(e) => updateFilter(operation, undefined)}>
179
+ <ClearIcon/>
180
+ </IconButton>}
181
+ // renderValues={(enumKeys) => {
182
+ // console.log("renderValues", enumKeys);
183
+ // if (enumKeys === null)
184
+ // return "Filter for null values";
185
+ //
186
+ // return enumKeys.map(key => <EnumValuesChip
187
+ // key={`select_value_${name}_${enumKeys}`}
188
+ // enumKey={key}
189
+ // enumValues={enumValues}
190
+ // size={"small"}/>);
191
+ // }}
192
+ >
193
+ {enumValues.map((enumConfig) => (
194
+ <MultiSelectItem key={`select_value_${name}_${enumConfig.id}`}
195
+ value={String(enumConfig.id)}>
196
+ <EnumValuesChip
197
+ enumKey={String(enumConfig.id)}
198
+ enumValues={enumValues}
199
+ size={"small"}/>
200
+ </MultiSelectItem>
201
+ ))}
202
+ </MultiSelect>
203
+ }
204
+
158
205
  {!isArray && <Label
159
206
  className="border cursor-pointer rounded-md p-2 flex items-center gap-2 [&:has(:checked)]:bg-gray-100 dark:[&:has(:checked)]:bg-gray-800"
160
207
  htmlFor="null-filter"
@@ -91,6 +91,7 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
91
91
  data,
92
92
  onResetPagination,
93
93
  onEndReached,
94
+ endOffset = 600,
94
95
  rowHeight = 54,
95
96
  columns: columnsProp,
96
97
  onRowClick,
@@ -110,7 +111,8 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
110
111
  style,
111
112
  className,
112
113
  endAdornment,
113
- AddColumnComponent
114
+ AddColumnComponent,
115
+ debug
114
116
  }: VirtualTableProps<T>) {
115
117
 
116
118
  const sortByProperty: string | undefined = sortBy ? sortBy[0] : undefined;
@@ -128,10 +130,14 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
128
130
  const [measureRef, bounds] = useMeasure();
129
131
 
130
132
  const onColumnResizeInternal = useCallback((params: OnVirtualTableColumnResizeParams) => {
133
+ if (debug)
134
+ console.log("onColumnResizeInternal", params);
131
135
  setColumns(columns.map((column) => column.key === params.column.key ? params.column : column));
132
136
  }, [columns]);
133
137
 
134
138
  const onColumnResizeEndInternal = useCallback((params: OnVirtualTableColumnResizeParams) => {
139
+ if (debug)
140
+ console.log("onColumnResizeEndInternal", params);
135
141
  setColumns(columns.map((column) => column.key === params.column.key ? params.column : column));
136
142
  if (onColumnResize) {
137
143
  onColumnResize(params);
@@ -142,10 +148,14 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
142
148
  const filterRef = useRef<VirtualTableFilterValues<any> | undefined>();
143
149
 
144
150
  useEffect(() => {
151
+ if (debug)
152
+ console.log("Filter updated", filterInput);
145
153
  filterRef.current = filterInput;
146
154
  }, [filterInput]);
147
155
 
148
156
  const scrollToTop = useCallback(() => {
157
+ if (debug)
158
+ console.log("scrollToTop");
149
159
  endReachCallbackThreshold.current = 0;
150
160
  if (tableRef.current) {
151
161
  // scrollRef.current = [scrollRef.current[0], 0];
@@ -155,6 +165,9 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
155
165
 
156
166
  const onColumnSort = useCallback((key: string) => {
157
167
 
168
+ if (debug)
169
+ console.log("onColumnSort", key);
170
+
158
171
  const isDesc = sortByProperty === key && currentSort === "desc";
159
172
  const isAsc = sortByProperty === key && currentSort === "asc";
160
173
  const newSort = isAsc ? "desc" : (isDesc ? undefined : "asc");
@@ -181,21 +194,21 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
181
194
  scrollToTop();
182
195
  }, [checkFilterCombination, currentSort, onFilterUpdate, onResetPagination, onSortByUpdate, scrollToTop, sortByProperty]);
183
196
 
184
- const resetSort = useCallback(() => {
185
- endReachCallbackThreshold.current = 0;
186
- if (onSortByUpdate)
187
- onSortByUpdate(undefined);
188
- }, [onSortByUpdate]);
189
-
190
197
  const maxScroll = Math.max((data?.length ?? 0) * rowHeight - bounds.height, 0);
198
+ if (debug)
199
+ console.log("maxScroll", maxScroll);
200
+
191
201
  const onEndReachedInternal = useCallback((scrollOffset: number) => {
192
- if (onEndReached && (data?.length ?? 0) > 0 && scrollOffset > endReachCallbackThreshold.current + 600) {
202
+ if (debug)
203
+ console.log("onEndReachedInternal", scrollOffset, endReachCallbackThreshold.current + endOffset);
204
+ if (onEndReached && (data?.length ?? 0) > 0 && scrollOffset > endReachCallbackThreshold.current + endOffset) {
193
205
  endReachCallbackThreshold.current = scrollOffset;
194
206
  onEndReached();
195
207
  }
196
208
  }, [data?.length, onEndReached]);
197
209
 
198
210
  const onScroll = useCallback(({
211
+ scrollDirection,
199
212
  scrollOffset,
200
213
  scrollUpdateWasRequested
201
214
  }: {
@@ -203,11 +216,19 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
203
216
  scrollOffset: number,
204
217
  scrollUpdateWasRequested: boolean;
205
218
  }) => {
206
- if (!scrollUpdateWasRequested && (scrollOffset >= maxScroll - 600))
219
+ if(debug)
220
+ console.log("onScroll", {
221
+ scrollDirection,
222
+ scrollOffset,
223
+ scrollUpdateWasRequested
224
+ });
225
+ if (!scrollUpdateWasRequested && (scrollOffset >= maxScroll - endOffset))
207
226
  onEndReachedInternal(scrollOffset);
208
227
  }, [maxScroll, onEndReachedInternal]);
209
228
 
210
229
  const onFilterUpdateInternal = useCallback((column: VirtualTableColumn, filterForProperty?: [VirtualTableWhereFilterOp, any]) => {
230
+ if(debug)
231
+ console.log("onFilterUpdateInternal", column, filterForProperty);
211
232
 
212
233
  endReachCallbackThreshold.current = 0;
213
234
  const filter = filterRef.current;
@@ -272,6 +293,9 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
272
293
  AddColumnComponent
273
294
  };
274
295
 
296
+ if(debug)
297
+ console.log("VirtualTable render", virtualListController);
298
+
275
299
  // useTraceUpdate(virtualListController);
276
300
  return (
277
301
  <div
@@ -16,7 +16,7 @@ type VirtualTableCellProps<T extends any> = {
16
16
  };
17
17
 
18
18
  export const VirtualTableCell = React.memo<VirtualTableCellProps<any>>(
19
- function VirtualTableCell<T extends any>(props: VirtualTableCellProps<T>) {
19
+ function VirtualTableCell<T>(props: VirtualTableCellProps<T>) {
20
20
  // @ts-ignore
21
21
  return props.rowData && props.cellRenderer(
22
22
  {
@@ -30,14 +30,6 @@ export const VirtualTableCell = React.memo<VirtualTableCellProps<any>>(
30
30
  width: props.column.width
31
31
  } as CellRendererParams<T>
32
32
  );
33
- // return props.rowData && <props.cellRenderer
34
- // rowData={props.rowData}
35
- // rowIndex={props.rowIndex}
36
- // isScrolling={false}
37
- // column={props.column}
38
- // columns={props.columns}
39
- // columnIndex={props.columnIndex}
40
- // width={props.column.width}/>
41
33
  },
42
34
  (a, b) => {
43
35
  return equal(a.rowData, b.rowData) &&
@@ -31,11 +31,6 @@ export interface VirtualTableProps<T extends Record<string, any>> {
31
31
  */
32
32
  cellRenderer: React.ComponentType<CellRendererParams<T>>;
33
33
 
34
- /**
35
- * If enabled, content is loaded in batch
36
- */
37
- paginationEnabled?: boolean;
38
-
39
34
  /**
40
35
  * Set this callback if you want to support some combinations
41
36
  * of filter combinations only.
@@ -50,6 +45,11 @@ export interface VirtualTableProps<T extends Record<string, any>> {
50
45
  */
51
46
  onEndReached?: () => void;
52
47
 
48
+ /**
49
+ * Offset in pixels where the onEndReached callback is triggered
50
+ */
51
+ endOffset?: number;
52
+
53
53
  /**
54
54
  * When the pagination should be reset. E.g. the filters or sorting
55
55
  * has been reset.
@@ -147,9 +147,14 @@ export interface VirtualTableProps<T extends Record<string, any>> {
147
147
  */
148
148
  AddColumnComponent?: React.ComponentType;
149
149
 
150
+ /**
151
+ * Debug mode
152
+ */
153
+ debug?: boolean;
154
+
150
155
  }
151
156
 
152
- export type CellRendererParams<T extends any = any> = {
157
+ export type CellRendererParams<T = any> = {
153
158
  column: VirtualTableColumn;
154
159
  columns: VirtualTableColumn[];
155
160
  columnIndex: number;
@@ -163,7 +168,7 @@ export type CellRendererParams<T extends any = any> = {
163
168
  * @see Table
164
169
  * @group Components
165
170
  */
166
- export interface VirtualTableColumn<CustomProps extends any = any> {
171
+ export interface VirtualTableColumn<CustomProps = any> {
167
172
 
168
173
  /**
169
174
  * Data key for the cell value, could be "a.b.c"
@@ -237,7 +242,6 @@ export type OnVirtualTableColumnResizeParams = {
237
242
  column: VirtualTableColumn
238
243
  };
239
244
 
240
-
241
245
  /**
242
246
  * @see Table
243
247
  * @group Components
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { DateTimeField } from "@firecms/ui";
2
+ import { cls, DateTimeField, focusedDisabled } from "@firecms/ui";
3
3
  import { useCustomizationController } from "../../../hooks";
4
4
 
5
5
  export function VirtualTableDateField(props: {
@@ -28,8 +28,8 @@ export function VirtualTableDateField(props: {
28
28
  onChange={(dateValue) => updateValue(dateValue ?? null)}
29
29
  size={"medium"}
30
30
  invisible={true}
31
- className={"w-full h-full"}
32
- inputClassName={"w-full h-full"}
31
+ inputClassName={cls("w-full h-full", focusedDisabled)}
32
+ className={cls("w-full h-full", focusedDisabled)}
33
33
  mode={mode}
34
34
  locale={locale}
35
35
  />
@@ -1,7 +1,7 @@
1
1
  import React, { useEffect, useRef, useState } from "react";
2
2
 
3
3
  import { useDebouncedCallback } from "../../../util";
4
- import { TextareaAutosize } from "@firecms/ui";
4
+ import { focusedDisabled, TextareaAutosize } from "@firecms/ui";
5
5
 
6
6
  export function VirtualTableInput(props: {
7
7
  error: Error | undefined;
@@ -58,6 +58,7 @@ export function VirtualTableInput(props: {
58
58
 
59
59
  return (
60
60
  <TextareaAutosize
61
+ className={focusedDisabled}
61
62
  ref={ref}
62
63
  style={{
63
64
  padding: 0,
@@ -1,5 +1,6 @@
1
1
  import React, { useEffect, useRef, useState } from "react";
2
2
  import { useDebouncedCallback } from "../../../util";
3
+ import { cls, focusedDisabled } from "@firecms/ui";
3
4
 
4
5
  export function VirtualTableNumberInput(props: {
5
6
  error: Error | undefined;
@@ -65,7 +66,7 @@ export function VirtualTableNumberInput(props: {
65
66
  return (
66
67
  <input
67
68
  ref={ref}
68
- className="w-full text-right p-0 m-0 bg-transparent border-none resize-none outline-none font-normal leading-normal text-unset"
69
+ className={cls("w-full text-right p-0 m-0 bg-transparent border-none resize-none outline-none font-normal leading-normal text-unset", focusedDisabled)}
69
70
  style={{
70
71
  textAlign: align
71
72
  }}
@@ -1,5 +1,5 @@
1
1
  import { EnumValueConfig } from "../../../types";
2
- import { ArrayEnumPreview, EnumValuesChip } from "../../../preview";
2
+ import { EnumValuesChip } from "../../../preview";
3
3
  import React, { useCallback, useEffect } from "react";
4
4
  import { MultiSelect, MultiSelectItem, Select, SelectItem } from "@firecms/ui";
5
5
 
@@ -18,9 +18,7 @@ export function VirtualTableSelect(props: {
18
18
  }) {
19
19
 
20
20
  const {
21
- name,
22
21
  enumValues,
23
- error,
24
22
  internalValue,
25
23
  disabled,
26
24
  small,
@@ -41,6 +39,7 @@ export function VirtualTableSelect(props: {
41
39
  }, [focused, ref]);
42
40
 
43
41
  const onChange = useCallback((updatedValue: string | string[]) => {
42
+ console.trace("onChange");
44
43
  if (valueType === "number") {
45
44
  if (multiple) {
46
45
  const newValue = (updatedValue as string[]).map((v) => parseFloat(v));
@@ -58,37 +57,27 @@ export function VirtualTableSelect(props: {
58
57
  }
59
58
  }, [multiple, updateValue, valueType]);
60
59
 
61
- const renderValue = (enumKey: string | number, index: number) => {
62
- if (multiple && Array.isArray(enumKey)) {
63
- return <ArrayEnumPreview
64
- key={`${enumKey}-${index}`}
65
- value={enumKey}
66
- name={name}
67
- enumValues={enumValues}
68
- size={small ? "small" : "medium"}/>;
69
- } else {
70
- return <EnumValuesChip
71
- key={`${enumKey}-${index}`}
72
- enumKey={enumKey}
73
- enumValues={enumValues}
74
- size={small ? "small" : "medium"}/>;
75
- }
60
+ const renderValue = (enumKey?: string | number) => {
61
+ return <EnumValuesChip
62
+ key={`${enumKey}`}
63
+ enumKey={String(enumKey)}
64
+ enumValues={enumValues}
65
+ size={small ? "small" : "medium"}/>;
76
66
  };
67
+
77
68
  return (
78
69
  multiple
79
70
  ? <MultiSelect
80
71
  inputRef={ref}
81
- containerClassName="w-full h-full"
82
72
  className="w-full h-full p-0 bg-transparent"
83
73
  position={"item-aligned"}
84
74
  disabled={disabled}
85
- padding={false}
86
- includeFocusOutline={false}
75
+ includeClear={false}
76
+ useChips={false}
87
77
  value={validValue
88
78
  ? ((internalValue as any[]).map(v => v.toString()))
89
79
  : ([])}
90
- onMultiValueChange={onChange}
91
- renderValue={renderValue}>
80
+ onValueChange={onChange}>
92
81
  {enumValues?.map((enumConfig) => (
93
82
  <MultiSelectItem
94
83
  key={enumConfig.id}
@@ -105,14 +94,11 @@ export function VirtualTableSelect(props: {
105
94
  className="w-full h-full p-0 bg-transparent"
106
95
  position={"item-aligned"}
107
96
  disabled={disabled}
108
- multiple={multiple}
109
97
  padding={false}
110
- includeFocusOutline={false}
111
98
  value={validValue
112
- ? (multiple ? (internalValue as any[]).map(v => v.toString()) : internalValue?.toString())
113
- : (multiple ? [] : "")}
99
+ ? internalValue?.toString()
100
+ : ""}
114
101
  onValueChange={onChange}
115
- onMultiValueChange={onChange}
116
102
  renderValue={renderValue}>
117
103
  {enumValues?.map((enumConfig) => (
118
104
  <SelectItem
@@ -106,3 +106,16 @@ export function getColumnKeysForProperty(property: ResolvedProperty, key: string
106
106
  disabled: disabled || Boolean(property.disabled) || Boolean(property.readOnly)
107
107
  }];
108
108
  }
109
+
110
+ export function getFormFieldKeys(collection: EntityCollection): string[] {
111
+ const propertyKeys = Object.keys(collection.properties);
112
+ const additionalFields = collection.additionalFields ?? [];
113
+ const allKeys = [
114
+ ...propertyKeys,
115
+ ...additionalFields.map((field) => field.key)
116
+ ];
117
+ if (collection.propertiesOrder) {
118
+ return collection.propertiesOrder.filter(key => allKeys.includes(key));
119
+ }
120
+ return allKeys;
121
+ }
@@ -80,6 +80,18 @@ export function useDataSourceEntityCollectionTableController<M extends Record<st
80
80
  const [searchString, setSearchString] = React.useState<string | undefined>();
81
81
  const [itemCount, setItemCount] = React.useState<number | undefined>(paginationEnabled ? pageSize : undefined);
82
82
 
83
+ const checkFilterCombination = useCallback((filterValues: FilterValues<any>,
84
+ sortBy?: [string, "asc" | "desc"]) => {
85
+ if (!dataSource.isFilterCombinationValid)
86
+ return true;
87
+ return dataSource.isFilterCombinationValid({
88
+ path: resolvedPath,
89
+ collection,
90
+ filterValues,
91
+ sortBy
92
+ })
93
+ }, []);
94
+
83
95
  const initialSortInternal = useMemo(() => {
84
96
  if (initialSort && forceFilter && !checkFilterCombination(forceFilter, initialSort)) {
85
97
  console.warn("Initial sort is not compatible with the force filter. Ignoring initial sort");
@@ -108,18 +120,6 @@ export function useDataSourceEntityCollectionTableController<M extends Record<st
108
120
  const [dataLoadingError, setDataLoadingError] = useState<Error | undefined>();
109
121
  const [noMoreToLoad, setNoMoreToLoad] = useState<boolean>(false);
110
122
 
111
- const checkFilterCombination = useCallback((filterValues: FilterValues<any>,
112
- sortBy?: [string, "asc" | "desc"]) => {
113
- if (!dataSource.isFilterCombinationValid)
114
- return true;
115
- return dataSource.isFilterCombinationValid({
116
- path: resolvedPath,
117
- collection,
118
- filterValues,
119
- sortBy
120
- })
121
- }, []);
122
-
123
123
  const clearFilter = useCallback(() => setFilterValues(forceFilter ?? undefined), [forceFilter]);
124
124
 
125
125
  const updateFilterValues = useCallback((updatedFilter: FilterValues<Extract<keyof M, string>> | undefined) => {
@@ -28,6 +28,7 @@ export function useTableSearchHelper<M extends Record<string, any>>({
28
28
  const props = {
29
29
  context,
30
30
  path: fullPath,
31
+ databaseId: collection.databaseId,
31
32
  collection,
32
33
  parentCollectionIds
33
34
  };
@@ -19,6 +19,7 @@ export * from "./EntityCollectionView/EntityCollectionViewActions";
19
19
  export * from "./EntityCollectionView/useSelectionController";
20
20
 
21
21
  export * from "./PropertyConfigBadge";
22
+ export * from "./PropertyIdCopyTooltip";
22
23
 
23
24
  export * from "./EntityCollectionTable";
24
25
  export * from "./NotFoundPage";
@@ -45,7 +45,7 @@ export type DefaultAppBarProps<ADDITIONAL_PROPS = object> = {
45
45
  * This component renders the main app bar of FireCMS.
46
46
  * You will likely not need to use this component directly.
47
47
  *
48
- * @constructor
48
+
49
49
  */
50
50
  export const DefaultAppBar = function DefaultAppBar({
51
51
  title,
@@ -95,7 +95,7 @@ export const DefaultAppBar = function DefaultAppBar({
95
95
  return (
96
96
  <div
97
97
  style={style}
98
- className={cls("pr-2 w-full h-16 transition-all ease-in duration-75 fixed",
98
+ className={cls("w-full h-16 transition-all ease-in duration-75 fixed",
99
99
  {
100
100
  "pl-[17rem]": drawerOpen && largeLayout,
101
101
  "pl-20": hasDrawer && !(drawerOpen && largeLayout),
@@ -124,7 +124,7 @@ export const DefaultAppBar = function DefaultAppBar({
124
124
  {typeof title === "string"
125
125
  ? <Typography variant="subtitle1"
126
126
  noWrap
127
- className={"ml-2 !font-medium"}>
127
+ className={cls("transition-all", drawerOpen ? "ml-2" : "")}>
128
128
  {title}
129
129
  </Typography>
130
130
  : title}
@@ -30,15 +30,15 @@ export function DefaultDrawer({
30
30
  logo
31
31
  } = useApp();
32
32
 
33
+ const [adminMenuOpen, setAdminMenuOpen] = React.useState(false);
34
+
33
35
  const analyticsController = useAnalyticsController();
34
36
  const navigation = useNavigationController();
35
37
 
36
- const tooltipsOpen = drawerHovered && !drawerOpen;
38
+ const tooltipsOpen = drawerHovered && !drawerOpen && !adminMenuOpen;
37
39
  const largeLayout = useLargeLayout();
38
40
  const navigate = useNavigate();
39
41
 
40
- const [adminMenuOpen, setAdminMenuOpen] = React.useState(false);
41
-
42
42
  if (!navigation.topLevelNavigation)
43
43
  throw Error("Navigation not ready in Drawer");
44
44
 
@@ -51,9 +51,9 @@ export function DefaultDrawer({
51
51
  const groupsWithoutAdmin = groups.filter(g => g !== "Admin");
52
52
 
53
53
  const buildGroupHeader = useCallback((group?: string) => {
54
- if (!drawerOpen) return <div className="h-12 w-full"/>;
54
+ if (!drawerOpen) return <div className="w-full"/>;
55
55
  return <div
56
- className="pt-8 pl-6 pr-8 pb-2 flex flex-row items-center">
56
+ className="pl-6 pr-8 py-4 flex flex-row items-center">
57
57
  <Typography variant={"caption"}
58
58
  color={"secondary"}
59
59
  className="font-medium flex-grow line-clamp-1">
@@ -78,10 +78,14 @@ export function DefaultDrawer({
78
78
 
79
79
  <DrawerLogo logo={logo}/>
80
80
 
81
- <div className={"overflow-scroll no-scrollbar"}>
81
+ <div className={"mt-4 flex-grow overflow-scroll no-scrollbar"}
82
+ style={{
83
+ maskImage: "linear-gradient(to bottom, transparent 0, black 20px, black calc(100% - 20px), transparent 100%)",
84
+ }}>
82
85
 
83
86
  {groupsWithoutAdmin.map((group) => (
84
- <React.Fragment
87
+ <div
88
+ className={"bg-gray-50 dark:bg-gray-800 dark:bg-opacity-30 my-4 rounded-lg ml-4"}
85
89
  key={`drawer_group_${group}`}>
86
90
  {buildGroupHeader(group)}
87
91
  {Object.values(navigationEntries)
@@ -89,18 +93,20 @@ export function DefaultDrawer({
89
93
  .map((view, index) =>
90
94
  <DrawerNavigationItem
91
95
  key={`navigation_${index}`}
92
- icon={<IconForView collectionOrView={view.collection ?? view.view}/>}
96
+ icon={<IconForView collectionOrView={view.collection ?? view.view} size={"small"}/>}
93
97
  tooltipsOpen={tooltipsOpen}
98
+ adminMenuOpen={adminMenuOpen}
94
99
  drawerOpen={drawerOpen}
95
100
  onClick={() => onClick(view)}
96
101
  url={view.url}
97
102
  name={view.name}/>)}
98
- </React.Fragment>
103
+ </div>
99
104
  ))}
100
105
 
101
106
  </div>
102
107
 
103
108
  {adminViews.length > 0 && <Menu
109
+ side={"right"}
104
110
  open={adminMenuOpen}
105
111
  onOpenChange={setAdminMenuOpen}
106
112
  trigger={
@@ -144,7 +150,7 @@ export function DefaultDrawer({
144
150
  * It expands when the drawer is open.
145
151
  *
146
152
  * @param logo
147
- * @constructor
153
+
148
154
  */
149
155
  export function DrawerLogo({ logo }: {
150
156
  logo?: string;
@@ -155,9 +161,9 @@ export function DrawerLogo({ logo }: {
155
161
  return <div
156
162
  style={{
157
163
  transition: "padding 100ms cubic-bezier(0.4, 0, 0.6, 1) 0ms",
158
- padding: drawerOpen ? "32px 144px 0px 24px" : "72px 16px 0px"
164
+ padding: drawerOpen ? "32px 144px 0px 24px" : "72px 12px 0px 12px"
159
165
  }}
160
- className={cls("cursor-pointer")}>
166
+ className={cls("cursor-pointer ml-4")}>
161
167
 
162
168
  <Tooltip title={"Home"}
163
169
  sideOffset={20}