@firecms/core 3.0.1 → 3.1.0-canary.24c8270

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 (186) hide show
  1. package/README.md +1 -1
  2. package/dist/components/AIIcon.d.ts +16 -0
  3. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +7 -1
  4. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +1 -1
  5. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +14 -0
  6. package/dist/components/EntityCollectionTable/PropertyTableCell.d.ts +6 -0
  7. package/dist/components/EntityCollectionTable/internal/CollectionTableToolbar.d.ts +5 -4
  8. package/dist/components/EntityCollectionTable/internal/EntityTableCell.d.ts +6 -0
  9. package/dist/components/EntityCollectionTable/internal/popup_field/useDraggable.d.ts +2 -2
  10. package/dist/components/EntityCollectionView/Board.d.ts +2 -0
  11. package/dist/components/EntityCollectionView/BoardColumn.d.ts +42 -0
  12. package/dist/components/EntityCollectionView/BoardColumnTitle.d.ts +9 -0
  13. package/dist/components/EntityCollectionView/BoardSortableList.d.ts +14 -0
  14. package/dist/components/EntityCollectionView/EntityBoardCard.d.ts +26 -0
  15. package/dist/components/EntityCollectionView/EntityCard.d.ts +19 -0
  16. package/dist/components/EntityCollectionView/EntityCollectionBoardView.d.ts +20 -0
  17. package/dist/components/EntityCollectionView/EntityCollectionCardView.d.ts +31 -0
  18. package/dist/components/EntityCollectionView/EntityCollectionViewActions.d.ts +2 -2
  19. package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +7 -3
  20. package/dist/components/EntityCollectionView/FiltersDialog.d.ts +14 -0
  21. package/dist/components/EntityCollectionView/ViewModeToggle.d.ts +44 -0
  22. package/dist/components/EntityCollectionView/board_types.d.ts +105 -0
  23. package/dist/components/EntityCollectionView/useBoardDataController.d.ts +60 -0
  24. package/dist/components/ErrorBoundary.d.ts +1 -1
  25. package/dist/components/SelectableTable/SelectableTable.d.ts +5 -1
  26. package/dist/components/SelectableTable/filters/DateTimeFilterField.d.ts +2 -1
  27. package/dist/components/VirtualTable/VirtualTableCell.d.ts +6 -0
  28. package/dist/components/VirtualTable/VirtualTableHeader.d.ts +3 -1
  29. package/dist/components/VirtualTable/VirtualTableHeaderRow.d.ts +1 -1
  30. package/dist/components/VirtualTable/VirtualTableProps.d.ts +11 -0
  31. package/dist/components/VirtualTable/fields/VirtualTableDateField.d.ts +1 -0
  32. package/dist/components/VirtualTable/types.d.ts +2 -0
  33. package/dist/components/index.d.ts +3 -0
  34. package/dist/contexts/index.d.ts +10 -0
  35. package/dist/core/DrawerNavigationGroup.d.ts +45 -0
  36. package/dist/core/index.d.ts +1 -0
  37. package/dist/form/components/ErrorFocus.d.ts +1 -1
  38. package/dist/form/validation.d.ts +3 -2
  39. package/dist/hooks/useBreadcrumbsController.d.ts +16 -0
  40. package/dist/hooks/useCollapsedGroups.d.ts +4 -1
  41. package/dist/index.es.js +5316 -1592
  42. package/dist/index.es.js.map +1 -1
  43. package/dist/index.umd.js +5309 -1586
  44. package/dist/index.umd.js.map +1 -1
  45. package/dist/internal/useRestoreScroll.d.ts +1 -1
  46. package/dist/preview/PropertyPreviewProps.d.ts +5 -0
  47. package/dist/preview/components/DatePreview.d.ts +13 -3
  48. package/dist/preview/components/ImagePreview.d.ts +5 -1
  49. package/dist/preview/components/StorageThumbnail.d.ts +2 -1
  50. package/dist/preview/components/UrlComponentPreview.d.ts +2 -1
  51. package/dist/preview/property_previews/ArrayOfStorageComponentsPreview.d.ts +1 -1
  52. package/dist/preview/property_previews/ArrayOfStringsPreview.d.ts +1 -1
  53. package/dist/preview/property_previews/SkeletonPropertyComponent.d.ts +1 -1
  54. package/dist/types/analytics.d.ts +1 -1
  55. package/dist/types/collections.d.ts +50 -2
  56. package/dist/types/datasource.d.ts +0 -1
  57. package/dist/types/plugins.d.ts +62 -1
  58. package/dist/types/properties.d.ts +259 -4
  59. package/dist/util/__tests__/conditions.test.d.ts +1 -0
  60. package/dist/util/__tests__/objects.test.d.ts +1 -0
  61. package/dist/util/conditions.d.ts +26 -0
  62. package/dist/util/entities.d.ts +2 -3
  63. package/dist/util/index.d.ts +2 -1
  64. package/dist/util/property_utils.d.ts +2 -1
  65. package/dist/util/resolutions.d.ts +3 -3
  66. package/package.json +14 -11
  67. package/src/app/Scaffold.tsx +14 -15
  68. package/src/components/AIIcon.tsx +39 -0
  69. package/src/components/ArrayContainer.tsx +1 -4
  70. package/src/components/ClearFilterSortButton.tsx +19 -16
  71. package/src/components/ConfirmationDialog.tsx +0 -2
  72. package/src/components/DeleteEntityDialog.tsx +2 -4
  73. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +74 -41
  74. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +130 -79
  75. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +121 -104
  76. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +132 -103
  77. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +20 -42
  78. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +90 -49
  79. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +1 -1
  80. package/src/components/EntityCollectionTable/internal/popup_field/useDraggable.tsx +11 -11
  81. package/src/components/EntityCollectionView/Board.tsx +324 -0
  82. package/src/components/EntityCollectionView/BoardColumn.tsx +158 -0
  83. package/src/components/EntityCollectionView/BoardColumnTitle.tsx +45 -0
  84. package/src/components/EntityCollectionView/BoardSortableList.tsx +172 -0
  85. package/src/components/EntityCollectionView/EntityBoardCard.tsx +212 -0
  86. package/src/components/EntityCollectionView/EntityCard.tsx +235 -0
  87. package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +733 -0
  88. package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +244 -0
  89. package/src/components/EntityCollectionView/EntityCollectionView.tsx +519 -203
  90. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +31 -19
  91. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +84 -15
  92. package/src/components/EntityCollectionView/FiltersDialog.tsx +249 -0
  93. package/src/components/EntityCollectionView/ViewModeToggle.tsx +199 -0
  94. package/src/components/EntityCollectionView/board_types.ts +113 -0
  95. package/src/components/EntityCollectionView/useBoardDataController.tsx +490 -0
  96. package/src/components/ErrorTooltip.tsx +2 -1
  97. package/src/components/HomePage/DefaultHomePage.tsx +47 -10
  98. package/src/components/HomePage/HomePageDnD.tsx +56 -41
  99. package/src/components/HomePage/NavigationCard.tsx +20 -18
  100. package/src/components/HomePage/NavigationGroup.tsx +17 -16
  101. package/src/components/HomePage/RenameGroupDialog.tsx +0 -2
  102. package/src/components/HomePage/SmallNavigationCard.tsx +10 -9
  103. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +3 -10
  104. package/src/components/ReferenceWidget.tsx +2 -4
  105. package/src/components/SelectableTable/SelectableTable.tsx +75 -67
  106. package/src/components/SelectableTable/filters/BooleanFilterField.tsx +7 -6
  107. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +39 -40
  108. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +38 -38
  109. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +49 -58
  110. package/src/components/UnsavedChangesDialog.tsx +0 -2
  111. package/src/components/UserDisplay.tsx +4 -4
  112. package/src/components/VirtualTable/VirtualTable.tsx +272 -118
  113. package/src/components/VirtualTable/VirtualTableCell.tsx +18 -2
  114. package/src/components/VirtualTable/VirtualTableHeader.tsx +59 -50
  115. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +158 -42
  116. package/src/components/VirtualTable/VirtualTableProps.tsx +14 -1
  117. package/src/components/VirtualTable/VirtualTableRow.tsx +1 -1
  118. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +3 -0
  119. package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +19 -6
  120. package/src/components/VirtualTable/types.tsx +2 -0
  121. package/src/components/common/useColumnsIds.tsx +95 -3
  122. package/src/components/common/useDataSourceTableController.tsx +21 -4
  123. package/src/components/index.tsx +4 -0
  124. package/src/contexts/BreacrumbsContext.tsx +15 -8
  125. package/src/contexts/index.ts +10 -0
  126. package/src/core/DefaultAppBar.tsx +40 -27
  127. package/src/core/DefaultDrawer.tsx +42 -56
  128. package/src/core/DrawerNavigationGroup.tsx +118 -0
  129. package/src/core/DrawerNavigationItem.tsx +4 -3
  130. package/src/core/EntityEditView.tsx +41 -43
  131. package/src/core/EntitySidePanel.tsx +28 -26
  132. package/src/core/SideDialogs.tsx +4 -2
  133. package/src/core/field_configs.tsx +14 -9
  134. package/src/core/index.tsx +1 -0
  135. package/src/form/EntityForm.tsx +69 -60
  136. package/src/form/PropertyFieldBinding.tsx +61 -46
  137. package/src/form/components/ErrorFocus.tsx +3 -3
  138. package/src/form/components/StorageItemPreview.tsx +2 -1
  139. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +0 -1
  140. package/src/form/field_bindings/DateTimeFieldBinding.tsx +17 -16
  141. package/src/form/field_bindings/KeyValueFieldBinding.tsx +0 -1
  142. package/src/form/field_bindings/MapFieldBinding.tsx +69 -67
  143. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +22 -18
  144. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +83 -83
  145. package/src/form/field_bindings/TextFieldBinding.tsx +71 -35
  146. package/src/form/validation.ts +245 -160
  147. package/src/hooks/useBreadcrumbsController.tsx +18 -0
  148. package/src/hooks/useBuildNavigationController.tsx +71 -28
  149. package/src/hooks/useCollapsedGroups.ts +12 -4
  150. package/src/hooks/useValidateAuthenticator.tsx +1 -1
  151. package/src/internal/useBuildDataSource.ts +68 -34
  152. package/src/internal/useBuildSideDialogsController.tsx +11 -8
  153. package/src/internal/useBuildSideEntityController.tsx +24 -24
  154. package/src/internal/useRestoreScroll.tsx +26 -14
  155. package/src/preview/PropertyPreview.tsx +41 -32
  156. package/src/preview/PropertyPreviewProps.tsx +6 -0
  157. package/src/preview/components/DatePreview.tsx +72 -4
  158. package/src/preview/components/EmptyValue.tsx +1 -1
  159. package/src/preview/components/ImagePreview.tsx +37 -21
  160. package/src/preview/components/StorageThumbnail.tsx +16 -12
  161. package/src/preview/components/UrlComponentPreview.tsx +28 -25
  162. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +9 -7
  163. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +11 -9
  164. package/src/preview/property_previews/ArrayPropertyPreview.tsx +26 -24
  165. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +61 -56
  166. package/src/routes/CustomCMSRoute.tsx +1 -0
  167. package/src/routes/FireCMSRoute.tsx +26 -13
  168. package/src/types/analytics.ts +10 -0
  169. package/src/types/collections.ts +57 -3
  170. package/src/types/datasource.ts +54 -56
  171. package/src/types/plugins.tsx +69 -1
  172. package/src/types/properties.ts +347 -27
  173. package/src/util/__tests__/conditions.test.ts +506 -0
  174. package/src/util/__tests__/objects.test.ts +196 -0
  175. package/src/util/callbacks.ts +6 -3
  176. package/src/util/collections.ts +51 -6
  177. package/src/util/conditions.ts +339 -0
  178. package/src/util/entities.ts +29 -30
  179. package/src/util/entity_cache.ts +2 -1
  180. package/src/util/index.ts +2 -1
  181. package/src/util/join_collections.ts +10 -8
  182. package/src/util/objects.ts +31 -13
  183. package/src/util/{references.ts → previews.ts} +16 -2
  184. package/src/util/property_utils.tsx +37 -11
  185. package/src/util/resolutions.ts +62 -58
  186. /package/dist/util/{references.d.ts → previews.d.ts} +0 -0
@@ -49,6 +49,13 @@ export interface PropertyTableCellProps<T extends CMSType> {
49
49
  path: string;
50
50
  disabled: boolean;
51
51
  enablePopupIcon?: boolean;
52
+ // Sortable props for dnd-kit integration
53
+ sortableNodeRef?: (node: HTMLElement | null) => void;
54
+ sortableStyle?: React.CSSProperties;
55
+ sortableAttributes?: Record<string, any>;
56
+ isDragging?: boolean;
57
+ isDraggable?: boolean;
58
+ frozen?: boolean;
52
59
  }
53
60
 
54
61
  function isStorageProperty(property: ResolvedProperty) {
@@ -69,19 +76,25 @@ function isStorageProperty(property: ResolvedProperty) {
69
76
 
70
77
  export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
71
78
  function PropertyTableCell<T extends CMSType, M extends Record<string, any>>({
72
- propertyKey,
73
- customFieldValidator,
74
- value,
75
- property,
76
- align,
77
- width,
78
- height,
79
- path,
80
- entity,
81
- readonly,
82
- disabled: disabledProp,
83
- enablePopupIcon = true
84
- }: PropertyTableCellProps<T>) {
79
+ propertyKey,
80
+ customFieldValidator,
81
+ value,
82
+ property,
83
+ align,
84
+ width,
85
+ height,
86
+ path,
87
+ entity,
88
+ readonly,
89
+ disabled: disabledProp,
90
+ enablePopupIcon = true,
91
+ sortableNodeRef,
92
+ sortableStyle,
93
+ sortableAttributes,
94
+ isDragging,
95
+ isDraggable,
96
+ frozen
97
+ }: PropertyTableCellProps<T>) {
85
98
 
86
99
  const {
87
100
  onValueChange,
@@ -240,7 +253,13 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
240
253
  align={align ?? "left"}
241
254
  fullHeight={false}
242
255
  disabledTooltip={disabledTooltip ?? (readOnlyProperty ? "Read only" : undefined)}
243
- disabled={true}>
256
+ disabled={true}
257
+ sortableNodeRef={sortableNodeRef}
258
+ sortableStyle={sortableStyle}
259
+ sortableAttributes={sortableAttributes}
260
+ isDragging={isDragging}
261
+ isDraggable={isDraggable}
262
+ frozen={frozen}>
244
263
  <PropertyPreview
245
264
  width={width}
246
265
  height={getRowHeight(size)}
@@ -261,32 +280,32 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
261
280
  const referenceValue = internalValue ? new EntityReference(internalValue, path) : undefined;
262
281
  innerComponent =
263
282
  <TableReferenceField name={propertyKey as string}
264
- internalValue={referenceValue}
265
- updateValue={(v) => updateValue(v ? (v as EntityReference).id : null)}
266
- disabled={disabled}
267
- size={size}
268
- path={path}
269
- multiselect={false}
270
- previewProperties={referenceProperty.previewProperties}
271
- includeId={referenceProperty.includeId}
272
- includeEntityLink={referenceProperty.includeEntityLink}
273
- title={stringProperty.name}
274
- forceFilter={referenceProperty.forceFilter}
283
+ internalValue={referenceValue}
284
+ updateValue={(v) => updateValue(v ? (v as EntityReference).id : null)}
285
+ disabled={disabled}
286
+ size={size}
287
+ path={path}
288
+ multiselect={false}
289
+ previewProperties={referenceProperty.previewProperties}
290
+ includeId={referenceProperty.includeId}
291
+ includeEntityLink={referenceProperty.includeEntityLink}
292
+ title={stringProperty.name}
293
+ forceFilter={referenceProperty.forceFilter}
275
294
  />;
276
295
  allowScroll = false;
277
296
  } else if (isAStorageProperty) {
278
297
  innerComponent = <TableStorageUpload error={validationError ?? error}
279
- disabled={disabled}
280
- focused={selected}
281
- selected={selected}
282
- openPopup={setPopupCell ? openPopup : undefined}
283
- property={property as ResolvedStringProperty | ResolvedArrayProperty<string[]>}
284
- entity={entity}
285
- path={path}
286
- value={internalValue}
287
- previewSize={getPreviewSizeFrom(size)}
288
- updateValue={updateValue}
289
- propertyKey={propertyKey as string}
298
+ disabled={disabled}
299
+ focused={selected}
300
+ selected={selected}
301
+ openPopup={setPopupCell ? openPopup : undefined}
302
+ property={property as ResolvedStringProperty | ResolvedArrayProperty<string[]>}
303
+ entity={entity}
304
+ path={path}
305
+ value={internalValue}
306
+ previewSize={getPreviewSizeFrom(size)}
307
+ updateValue={updateValue}
308
+ propertyKey={propertyKey as string}
290
309
  />;
291
310
  includeActions = false;
292
311
  showExpandIcon = true;
@@ -296,15 +315,15 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
296
315
  const numberProperty = property as ResolvedNumberProperty;
297
316
  if (numberProperty.enumValues) {
298
317
  innerComponent = <VirtualTableSelect name={propertyKey as string}
299
- multiple={false}
300
- disabled={disabled}
301
- focused={selected}
302
- valueType={"number"}
303
- small={getPreviewSizeFrom(size) !== "medium"}
304
- enumValues={numberProperty.enumValues}
305
- error={validationError ?? error}
306
- internalValue={internalValue as string | number}
307
- updateValue={updateValue}
318
+ multiple={false}
319
+ disabled={disabled}
320
+ focused={selected}
321
+ valueType={"number"}
322
+ small={getPreviewSizeFrom(size) !== "medium"}
323
+ enumValues={numberProperty.enumValues}
324
+ error={validationError ?? error}
325
+ internalValue={internalValue as string | number}
326
+ updateValue={updateValue}
308
327
  />;
309
328
  fullHeight = true;
310
329
  } else {
@@ -322,54 +341,55 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
322
341
  const stringProperty = property as ResolvedStringProperty;
323
342
  if (stringProperty.enumValues) {
324
343
  innerComponent = <VirtualTableSelect name={propertyKey as string}
325
- multiple={false}
326
- focused={selected}
327
- disabled={disabled}
328
- valueType={"string"}
329
- small={getPreviewSizeFrom(size) !== "medium"}
330
- enumValues={stringProperty.enumValues}
331
- error={validationError ?? error}
332
- internalValue={internalValue as string | number}
333
- updateValue={updateValue}
344
+ multiple={false}
345
+ focused={selected}
346
+ disabled={disabled}
347
+ valueType={"string"}
348
+ small={getPreviewSizeFrom(size) !== "medium"}
349
+ enumValues={stringProperty.enumValues}
350
+ error={validationError ?? error}
351
+ internalValue={internalValue as string | number}
352
+ updateValue={updateValue}
334
353
  />;
335
354
  fullHeight = true;
336
355
  } else if (stringProperty.userSelect) {
337
356
  innerComponent = <VirtualTableUserSelect name={propertyKey as string}
338
- multiple={false}
339
- focused={selected}
340
- disabled={disabled}
341
- small={getPreviewSizeFrom(size) !== "medium"}
342
- error={validationError ?? error}
343
- internalValue={internalValue as string}
344
- updateValue={updateValue}
357
+ multiple={false}
358
+ focused={selected}
359
+ disabled={disabled}
360
+ small={getPreviewSizeFrom(size) !== "medium"}
361
+ error={validationError ?? error}
362
+ internalValue={internalValue as string}
363
+ updateValue={updateValue}
345
364
  />;
346
365
  fullHeight = true;
347
366
  } else if (stringProperty.markdown || !stringProperty.storage || !stringProperty.reference) {
348
367
  const multiline = Boolean(stringProperty.multiline) || Boolean(stringProperty.markdown);
349
368
  innerComponent = <VirtualTableInput error={validationError ?? error}
350
- disabled={disabled}
351
- multiline={multiline}
352
- focused={selected}
353
- value={internalValue as string}
354
- updateValue={updateValue}
369
+ disabled={disabled}
370
+ multiline={multiline}
371
+ focused={selected}
372
+ value={internalValue as string}
373
+ updateValue={updateValue}
355
374
  />;
356
375
  allowScroll = true;
357
376
  }
358
377
  } else if (property.dataType === "boolean") {
359
378
  innerComponent = <VirtualTableSwitch error={validationError ?? error}
360
- disabled={disabled}
361
- focused={selected}
362
- internalValue={internalValue as boolean}
363
- updateValue={updateValue}
379
+ disabled={disabled}
380
+ focused={selected}
381
+ internalValue={internalValue as boolean}
382
+ updateValue={updateValue}
364
383
  />;
365
384
  } else if (property.dataType === "date") {
366
385
  innerComponent = <VirtualTableDateField name={propertyKey as string}
367
- error={validationError ?? error}
368
- disabled={disabled}
369
- mode={property.mode}
370
- focused={selected}
371
- internalValue={internalValue as Date}
372
- updateValue={updateValue}
386
+ error={validationError ?? error}
387
+ disabled={disabled}
388
+ mode={property.mode}
389
+ timezone={property.timezone}
390
+ focused={selected}
391
+ internalValue={internalValue as Date}
392
+ updateValue={updateValue}
373
393
  />;
374
394
  fullHeight = true;
375
395
  hideOverflow = false;
@@ -378,17 +398,17 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
378
398
  if (typeof property.path === "string") {
379
399
  innerComponent =
380
400
  <TableReferenceField name={propertyKey as string}
381
- internalValue={internalValue as EntityReference}
382
- updateValue={updateValue}
383
- disabled={disabled}
384
- size={size}
385
- path={property.path}
386
- multiselect={false}
387
- previewProperties={property.previewProperties}
388
- includeId={property.includeId}
389
- includeEntityLink={property.includeEntityLink}
390
- title={property.name}
391
- forceFilter={property.forceFilter}
401
+ internalValue={internalValue as EntityReference}
402
+ updateValue={updateValue}
403
+ disabled={disabled}
404
+ size={size}
405
+ path={property.path}
406
+ multiselect={false}
407
+ previewProperties={property.previewProperties}
408
+ includeId={property.includeId}
409
+ includeEntityLink={property.includeEntityLink}
410
+ title={property.name}
411
+ forceFilter={property.forceFilter}
392
412
  />;
393
413
  }
394
414
  allowScroll = false;
@@ -403,15 +423,15 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
403
423
  if (selected && arrayProperty.of.enumValues) {
404
424
  innerComponent =
405
425
  <VirtualTableSelect name={propertyKey as string}
406
- multiple={true}
407
- disabled={disabled}
408
- focused={selected}
409
- small={getPreviewSizeFrom(size) !== "medium"}
410
- valueType={arrayProperty.of.dataType}
411
- enumValues={arrayProperty.of.enumValues}
412
- error={validationError ?? error}
413
- internalValue={internalValue as string | number}
414
- updateValue={updateValue}
426
+ multiple={true}
427
+ disabled={disabled}
428
+ focused={selected}
429
+ small={getPreviewSizeFrom(size) !== "medium"}
430
+ valueType={arrayProperty.of.dataType}
431
+ enumValues={arrayProperty.of.enumValues}
432
+ error={validationError ?? error}
433
+ internalValue={internalValue as string | number}
434
+ updateValue={updateValue}
415
435
  />;
416
436
  allowScroll = true;
417
437
  fullHeight = true;
@@ -447,11 +467,11 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
447
467
  showExpandIcon = enablePopupIcon && selected && !innerComponent && !disabled && !readOnlyProperty;
448
468
  innerComponent = (
449
469
  <PropertyPreview width={width}
450
- height={height}
451
- propertyKey={propertyKey as string}
452
- value={internalValue}
453
- property={property}
454
- size={getPreviewSizeFrom(size)}
470
+ height={height}
471
+ propertyKey={propertyKey as string}
472
+ value={internalValue}
473
+ property={property}
474
+ size={getPreviewSizeFrom(size)}
455
475
  />
456
476
  );
457
477
  }
@@ -474,12 +494,18 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
474
494
  showExpandIcon={showExpandIcon}
475
495
  value={internalValue}
476
496
  hideOverflow={hideOverflow}
497
+ sortableNodeRef={sortableNodeRef}
498
+ sortableStyle={sortableStyle}
499
+ sortableAttributes={sortableAttributes}
500
+ isDragging={isDragging}
501
+ isDraggable={isDraggable}
502
+ frozen={frozen}
477
503
  actions={includeActions && <EntityTableCellActions
478
504
  showError={showError}
479
505
  disabled={disabled}
480
506
  showExpandIcon={showExpandIcon}
481
507
  selected={selected}
482
- openPopup={!disabled ? openPopup : undefined}/>}
508
+ openPopup={!disabled ? openPopup : undefined} />}
483
509
  >
484
510
 
485
511
  {innerComponent}
@@ -498,6 +524,9 @@ function areEqual(prevProps: PropertyTableCellProps<any>, nextProps: PropertyTab
498
524
  equal(prevProps.property, nextProps.property) &&
499
525
  equal(prevProps.value, nextProps.value) &&
500
526
  equal(prevProps.entity.id, nextProps.entity.id) &&
501
- equal(prevProps.entity.values, nextProps.entity.values)
527
+ equal(prevProps.entity.values, nextProps.entity.values) &&
528
+ prevProps.isDragging === nextProps.isDragging &&
529
+ prevProps.isDraggable === nextProps.isDraggable &&
530
+ prevProps.frozen === nextProps.frozen
502
531
  ;
503
532
  }
@@ -1,42 +1,37 @@
1
1
  import React, { useEffect } from "react";
2
2
 
3
3
  import {
4
- Button,
5
4
  CircularProgress,
6
5
  cls,
7
6
  defaultBorderMixin,
8
- FilterListOffIcon,
9
- SearchBar,
10
- Select,
11
- SelectItem,
12
- Tooltip
7
+ SearchBar
13
8
  } from "@firecms/ui";
14
- import { CollectionSize } from "../../../types";
15
9
  import { useLargeLayout } from "../../../hooks";
16
10
 
17
11
  interface CollectionTableToolbarProps {
18
- size: CollectionSize;
19
12
  loading: boolean;
20
13
  actionsStart?: React.ReactNode;
21
14
  actions?: React.ReactNode;
15
+ /**
16
+ * View mode toggle button, positioned left of the search bar.
17
+ */
18
+ viewModeToggle?: React.ReactNode;
22
19
  title?: React.ReactNode,
23
20
  onTextSearchClick?: () => void;
24
21
  onTextSearch?: (searchString?: string) => void;
25
- onSizeChanged: (size: CollectionSize) => void;
26
22
  textSearchLoading?: boolean;
27
23
  }
28
24
 
29
25
  export function CollectionTableToolbar({
30
- actions,
31
- actionsStart,
32
- loading,
33
- onSizeChanged,
34
- onTextSearch,
35
- onTextSearchClick,
36
- size,
37
- textSearchLoading,
38
- title
39
- }: CollectionTableToolbarProps) {
26
+ actions,
27
+ actionsStart,
28
+ loading,
29
+ onTextSearch,
30
+ onTextSearchClick,
31
+ textSearchLoading,
32
+ title,
33
+ viewModeToggle
34
+ }: CollectionTableToolbarProps) {
40
35
 
41
36
  const searchInputRef = React.useRef<HTMLInputElement>(null);
42
37
  const largeLayout = useLargeLayout();
@@ -51,36 +46,18 @@ export function CollectionTableToolbar({
51
46
  }, [textSearchLoading]);
52
47
 
53
48
 
54
- const sizeSelect = (
55
- <Tooltip title={"Table row size"} side={"right"} sideOffset={4}>
56
- <Select
57
- value={size as string}
58
- className="w-16 ml-2"
59
- size={"small"}
60
- onValueChange={(v) => onSizeChanged(v as CollectionSize)}
61
- renderValue={(v) => <div className={"font-medium"}>{v.toUpperCase()}</div>}
62
- >
63
- {["xs", "s", "m", "l", "xl"].map((size) => (
64
- <SelectItem key={size} value={size} className={"w-12 font-medium text-center"}>
65
- {size.toUpperCase()}
66
- </SelectItem>
67
- ))}
68
- </Select>
69
- </Tooltip>
70
- );
71
-
72
49
  return (
73
50
  <div
74
- className={cls(defaultBorderMixin, "no-scrollbar min-h-[56px] overflow-x-auto px-2 md:px-4 bg-surface-50 dark:bg-surface-900 border-b flex flex-row justify-between items-center w-full")}>
51
+ className={cls(defaultBorderMixin, "no-scrollbar min-h-[52px] overflow-x-auto px-2 md:px-4 bg-surface-50 dark:bg-surface-900 border-b flex flex-row justify-between items-center w-full")}>
75
52
 
76
53
  <div className="flex items-center gap-1 md:mr-4 mr-2">
77
54
 
55
+ {viewModeToggle}
56
+
78
57
  {title && <div className={"hidden lg:block"}>
79
58
  {title}
80
59
  </div>}
81
60
 
82
- {sizeSelect}
83
-
84
61
  {actionsStart}
85
62
 
86
63
  </div>
@@ -89,18 +66,19 @@ export function CollectionTableToolbar({
89
66
 
90
67
  {largeLayout && <div className="w-[22px] mr-4">
91
68
  {loading &&
92
- <CircularProgress size={"smallest"}/>}
69
+ <CircularProgress size={"smallest"} />}
93
70
  </div>}
94
71
 
95
72
  {(onTextSearch || onTextSearchClick) &&
96
73
  <SearchBar
97
74
  key={"search-bar"}
75
+ size={"small"}
98
76
  inputRef={searchInputRef}
99
77
  loading={textSearchLoading}
100
78
  disabled={Boolean(onTextSearchClick)}
101
79
  onClick={onTextSearchClick}
102
80
  onTextSearch={onTextSearchClick ? undefined : onTextSearch}
103
- expandable={true}/>}
81
+ expandable={true} />}
104
82
 
105
83
  {actions}
106
84
 
@@ -28,6 +28,13 @@ interface EntityTableCellProps {
28
28
  selected?: boolean;
29
29
  hideOverflow?: boolean;
30
30
  onSelect?: (cellRect: DOMRect | undefined) => void;
31
+ // Sortable props for dnd-kit integration
32
+ sortableNodeRef?: (node: HTMLElement | null) => void;
33
+ sortableStyle?: React.CSSProperties;
34
+ sortableAttributes?: Record<string, any>;
35
+ isDragging?: boolean;
36
+ isDraggable?: boolean;
37
+ frozen?: boolean;
31
38
  }
32
39
 
33
40
  type TableCellInnerProps = {
@@ -39,28 +46,28 @@ type TableCellInnerProps = {
39
46
  }
40
47
 
41
48
  const TableCellInner = ({
42
- justifyContent,
43
- scrollable,
44
- faded,
45
- fullHeight,
46
- children
47
- }: TableCellInnerProps) => {
49
+ justifyContent,
50
+ scrollable,
51
+ faded,
52
+ fullHeight,
53
+ children
54
+ }: TableCellInnerProps) => {
48
55
  return (
49
56
  <div className={cls("flex flex-col max-h-full w-full",
50
57
  {
51
58
  "items-start": faded || scrollable
52
59
  })}
53
- style={{
54
- justifyContent,
55
- height: fullHeight ? "100%" : undefined,
56
- overflow: scrollable ? "auto" : undefined,
57
- WebkitMaskImage: faded
58
- ? "linear-gradient(to bottom, black 60%, transparent 100%)"
59
- : undefined,
60
- maskImage: faded
61
- ? "linear-gradient(to bottom, black 60%, transparent 100%)"
62
- : undefined
63
- }}
60
+ style={{
61
+ justifyContent,
62
+ height: fullHeight ? "100%" : undefined,
63
+ overflow: scrollable ? "auto" : undefined,
64
+ WebkitMaskImage: faded
65
+ ? "linear-gradient(to bottom, black 60%, transparent 100%)"
66
+ : undefined,
67
+ maskImage: faded
68
+ ? "linear-gradient(to bottom, black 60%, transparent 100%)"
69
+ : undefined
70
+ }}
64
71
  >
65
72
  {children}
66
73
  </div>
@@ -69,23 +76,29 @@ const TableCellInner = ({
69
76
 
70
77
  export const EntityTableCell = React.memo<EntityTableCellProps>(
71
78
  function EntityTableCell({
72
- children,
73
- actions,
74
- size,
75
- selected,
76
- disabled,
77
- disabledTooltip,
78
- saved,
79
- error,
80
- align,
81
- allowScroll,
82
- removePadding,
83
- fullHeight,
84
- onSelect,
85
- width,
86
- hideOverflow = true,
87
- showExpandIcon = true
88
- }: EntityTableCellProps) {
79
+ children,
80
+ actions,
81
+ size,
82
+ selected,
83
+ disabled,
84
+ disabledTooltip,
85
+ saved,
86
+ error,
87
+ align,
88
+ allowScroll,
89
+ removePadding,
90
+ fullHeight,
91
+ onSelect,
92
+ width,
93
+ hideOverflow = true,
94
+ showExpandIcon = true,
95
+ sortableNodeRef,
96
+ sortableStyle,
97
+ sortableAttributes,
98
+ isDragging,
99
+ isDraggable,
100
+ frozen
101
+ }: EntityTableCellProps) {
89
102
 
90
103
  const [measureRef, bounds] = useMeasure();
91
104
  const ref = useRef<HTMLDivElement>(null);
@@ -188,9 +201,9 @@ export const EntityTableCell = React.memo<EntityTableCellProps>(
188
201
  <div
189
202
  className={cls(
190
203
  "transition-colors duration-100 ease-in-out",
191
- `flex relative h-full rounded-md p-${p} border border-4 border-opacity-75`,
204
+ `flex relative h-full rounded-md p-${p} border border-4 border-opacity-75`,
192
205
  onHover && !disabled ? "bg-surface-50 dark:bg-surface-900" : "",
193
- saved ? "bg-surface-100 bg-opacity-75 dark:bg-surface-800 dark:bg-opacity-75" : "",
206
+ saved ? "bg-surface-100/75 dark:bg-surface-800/75" : "",
194
207
  hideOverflow ? "overflow-hidden" : "",
195
208
  isSelected ? "bg-surface-50 dark:bg-surface-900" : "",
196
209
  borderClass
@@ -220,12 +233,12 @@ export const EntityTableCell = React.memo<EntityTableCellProps>(
220
233
  faded={faded}>
221
234
 
222
235
  {!fullHeight && <div ref={measureRef}
223
- style={{
224
- display: "flex",
225
- width: "100%",
226
- justifyContent,
227
- height: fullHeight ? "100%" : undefined
228
- }}>
236
+ style={{
237
+ display: "flex",
238
+ width: "100%",
239
+ justifyContent,
240
+ height: fullHeight ? "100%" : undefined
241
+ }}>
229
242
  {children}
230
243
  </div>}
231
244
 
@@ -237,22 +250,47 @@ export const EntityTableCell = React.memo<EntityTableCellProps>(
237
250
  {disabled && onHover && disabledTooltip &&
238
251
  <div className="absolute top-1 right-1 text-xs">
239
252
  <Tooltip title={disabledTooltip}>
240
- <DoNotDisturbOnIcon size={"smallest"} color={"disabled"} className={"text-surface-500"}/>
253
+ <DoNotDisturbOnIcon size={"smallest"} color={"disabled"} className={"text-text-disabled"} />
241
254
  </Tooltip>
242
255
  </div>}
243
256
 
244
257
  </div>
245
258
  </>;
246
- if (showError) {
247
- return (
259
+
260
+ // Wrap with sortable outer div when sortable props are provided
261
+ // Remove tabIndex from attributes to avoid capturing focus before cell content
262
+ const { tabIndex: _tabIndex, ...sortableAttrsWithoutTabIndex } = sortableAttributes ?? {};
263
+ const sortableContent = sortableNodeRef ? (
264
+ <div
265
+ ref={sortableNodeRef}
266
+ style={sortableStyle}
267
+ className={cls(
268
+ "flex-shrink-0",
269
+ frozen && "sticky left-0 z-10 bg-white dark:bg-surface-950"
270
+ )}
271
+ {...sortableAttrsWithoutTabIndex}
272
+ >
273
+ {showError ? (
274
+ <ErrorTooltip
275
+ className={"flex h-full w-full"}
276
+ align={"start"}
277
+ title={error?.message ?? "Error"}>
278
+ {result}
279
+ </ErrorTooltip>
280
+ ) : result}
281
+ </div>
282
+ ) : (
283
+ showError ? (
248
284
  <ErrorTooltip
285
+ className={"flex h-full w-full"}
249
286
  align={"start"}
250
287
  title={error?.message ?? "Error"}>
251
288
  {result}
252
289
  </ErrorTooltip>
253
- );
254
- }
255
- return result;
290
+ ) : result
291
+ );
292
+
293
+ return sortableContent;
256
294
  }, (a, b) => {
257
295
  return a.error === b.error &&
258
296
  a.value === b.value &&
@@ -266,5 +304,8 @@ export const EntityTableCell = React.memo<EntityTableCellProps>(
266
304
  a.showExpandIcon === b.showExpandIcon &&
267
305
  a.removePadding === b.removePadding &&
268
306
  a.fullHeight === b.fullHeight &&
269
- a.selected === b.selected;
307
+ a.selected === b.selected &&
308
+ a.isDragging === b.isDragging &&
309
+ a.isDraggable === b.isDraggable &&
310
+ a.frozen === b.frozen;
270
311
  }) as React.FunctionComponent<EntityTableCellProps>;