@firecms/core 3.0.0-alpha.20 → 3.0.0-alpha.24

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 (52) hide show
  1. package/dist/components/TextareaAutosize.d.ts +2 -0
  2. package/dist/components/index.d.ts +2 -0
  3. package/dist/core/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +7 -1
  4. package/dist/core/components/EntityCollectionTable/fields/TableReferenceField.d.ts +4 -2
  5. package/dist/core/components/EntityCollectionTable/useEntityCollectionTableController.d.ts +1 -1
  6. package/dist/core/components/VirtualTable/VirtualTableHeader.d.ts +1 -0
  7. package/dist/core/components/VirtualTable/VirtualTableHeaderRow.d.ts +1 -1
  8. package/dist/core/components/VirtualTable/VirtualTableProps.d.ts +12 -0
  9. package/dist/core/components/VirtualTable/types.d.ts +2 -0
  10. package/dist/core/form_field_configs.d.ts +1 -1
  11. package/dist/core/util/index.d.ts +1 -0
  12. package/dist/core/util/make_properties_editable.d.ts +3 -0
  13. package/dist/core/util/property_utils.d.ts +2 -1
  14. package/dist/index.es.js +8605 -8489
  15. package/dist/index.es.js.map +1 -1
  16. package/dist/index.umd.js +105 -105
  17. package/dist/index.umd.js.map +1 -1
  18. package/dist/types/collections.d.ts +1 -0
  19. package/dist/types/firecms.d.ts +14 -5
  20. package/dist/types/firecms_context.d.ts +8 -0
  21. package/dist/types/plugins.d.ts +22 -0
  22. package/package.json +137 -136
  23. package/src/components/BooleanSwitch.tsx +1 -1
  24. package/src/components/BooleanSwitchWithLabel.tsx +2 -2
  25. package/src/components/CircularProgress.tsx +1 -1
  26. package/src/components/Select.tsx +0 -12
  27. package/src/components/TextField.tsx +5 -6
  28. package/src/components/TextareaAutosize.tsx +8 -4
  29. package/src/components/index.tsx +2 -0
  30. package/src/core/FireCMS.tsx +5 -3
  31. package/src/core/components/EntityCollectionTable/EntityCollectionTable.tsx +11 -3
  32. package/src/core/components/EntityCollectionTable/EntityCollectionTableProps.tsx +11 -1
  33. package/src/core/components/EntityCollectionTable/fields/TableReferenceField.tsx +25 -12
  34. package/src/core/components/EntityCollectionTable/internal/PropertyTableCell.tsx +4 -2
  35. package/src/core/components/EntityCollectionTable/useEntityCollectionTableController.tsx +1 -1
  36. package/src/core/components/EntityCollectionView/EntityCollectionView.tsx +55 -3
  37. package/src/core/components/VirtualTable/VirtualTable.tsx +19 -7
  38. package/src/core/components/VirtualTable/VirtualTableHeader.tsx +26 -24
  39. package/src/core/components/VirtualTable/VirtualTableHeaderRow.tsx +7 -2
  40. package/src/core/components/VirtualTable/VirtualTableProps.tsx +14 -0
  41. package/src/core/components/VirtualTable/VirtualTableRow.tsx +1 -1
  42. package/src/core/components/VirtualTable/types.tsx +2 -0
  43. package/src/core/util/index.ts +1 -0
  44. package/src/core/util/make_properties_editable.ts +28 -0
  45. package/src/core/util/property_utils.tsx +6 -1
  46. package/src/form/components/LabelWithIcon.tsx +2 -3
  47. package/src/form/field_bindings/TextFieldBinding.tsx +1 -2
  48. package/src/preview/components/ReferencePreview.tsx +23 -3
  49. package/src/types/collections.ts +2 -0
  50. package/src/types/firecms.tsx +18 -6
  51. package/src/types/firecms_context.tsx +9 -0
  52. package/src/types/plugins.tsx +24 -1
@@ -395,6 +395,7 @@ export type TableController<M extends Record<string, any> = any> = {
395
395
  checkFilterCombination?: (filterValues: FilterValues<any>, sortBy?: [string, "asc" | "desc"]) => boolean;
396
396
  popupCell?: SelectedCellProps<M>;
397
397
  setPopupCell?: (popupCell?: SelectedCellProps<M>) => void;
398
+ onAddColumn?: (column: string) => void;
398
399
  };
399
400
  export type SelectedCellProps<M extends Record<string, any>> = {
400
401
  propertyKey: Extract<keyof M, string>;
@@ -1,3 +1,4 @@
1
+ import React from "react";
1
2
  import { User } from "./user";
2
3
  import { AuthController } from "./auth";
3
4
  import { DataSource } from "./datasource";
@@ -108,11 +109,6 @@ export type FireCMSProps<UserType extends User> = {
108
109
  * Delegate for implementing your auth operations.
109
110
  */
110
111
  authController: AuthController<UserType>;
111
- /**
112
- * Optional link builder you can add to generate a button in your entity forms.
113
- * The function must return a URL that gets opened when the button is clicked
114
- */
115
- entityLinkBuilder?: EntityLinkBuilder;
116
112
  /**
117
113
  * Path under the navigation routes of the CMS will be created. Defaults to `/`.
118
114
  * Internally FireCMS uses `react-router` to create the routes, the base path is attached to the
@@ -139,4 +135,17 @@ export type FireCMSProps<UserType extends User> = {
139
135
  * Callback used to get analytics events from the CMS
140
136
  */
141
137
  onAnalyticsEvent?: (event: CMSAnalyticsEvent, data?: object) => void;
138
+ /**
139
+ * Optional link builder you can add to generate a button in your entity forms.
140
+ * The function must return a URL that gets opened when the button is clicked
141
+ */
142
+ entityLinkBuilder?: EntityLinkBuilder;
143
+ components?: {
144
+ /**
145
+ * Component to render when a reference is missing
146
+ */
147
+ missingReference?: React.ComponentType<{
148
+ path: string;
149
+ }>;
150
+ };
142
151
  };
@@ -92,4 +92,12 @@ export type FireCMSContext<UserType extends User = User, AuthControllerType exte
92
92
  * You can also define an entity view from the UI.
93
93
  */
94
94
  entityViews?: EntityCustomView[];
95
+ components?: {
96
+ /**
97
+ * Component to render when a reference is missing
98
+ */
99
+ missingReference?: React.ComponentType<{
100
+ path: string;
101
+ }>;
102
+ };
95
103
  };
@@ -84,6 +84,28 @@ export type FireCMSPlugin<PROPS = any, FORM_PROPS = any> = {
84
84
  children: React.ReactNode;
85
85
  };
86
86
  };
87
+ collectionView?: {
88
+ /**
89
+ * Use this method to inject widgets to the entity collections header
90
+ * @param props
91
+ */
92
+ HeaderAction?: React.ComponentType<{
93
+ property: ResolvedProperty;
94
+ propertyKey: string;
95
+ onHover: boolean;
96
+ fullPath: string;
97
+ parentPathSegments: string[];
98
+ }>;
99
+ /**
100
+ * If you add this callback to your plugin, an add button will be added to the collection table.
101
+ * TODO: Only the first plugin that defines this callback will be used, at the moment.
102
+ */
103
+ AddColumnComponent?: React.ComponentType<{
104
+ fullPath: string;
105
+ parentPathSegments: string[];
106
+ collection: EntityCollection;
107
+ }>;
108
+ };
87
109
  };
88
110
  /**
89
111
  * Props passed to the {@link FireCMSPlugin.homePage.CollectionActions} method.
package/package.json CHANGED
@@ -1,139 +1,140 @@
1
1
  {
2
- "name": "@firecms/core",
3
- "version": "3.0.0-alpha.20",
4
- "description": "Awesome Firebase/Firestore-based headless open-source CMS",
5
- "funding": {
6
- "url": "https://github.com/sponsors/firecmsco"
2
+ "name": "@firecms/core",
3
+ "version": "3.0.0-alpha.24",
4
+ "description": "Awesome Firebase/Firestore-based headless open-source CMS",
5
+ "funding": {
6
+ "url": "https://github.com/sponsors/firecmsco"
7
+ },
8
+ "author": "FireCMS",
9
+ "license": "MIT",
10
+ "repository": "git@github.com:FireCMSco/firecms.git",
11
+ "main": "./dist/index.umd.js",
12
+ "module": "./dist/index.es.js",
13
+ "types": "./dist/index.d.ts",
14
+ "source": "src/index.ts",
15
+ "engines": {
16
+ "node": ">=14"
17
+ },
18
+ "exports": {
19
+ ".": {
20
+ "import": "./dist/index.es.js",
21
+ "require": "./dist/index.umd.js",
22
+ "types": "./dist/index.d.ts"
7
23
  },
8
- "author": "FireCMS",
9
- "license": "MIT",
10
- "repository": "git@github.com:FireCMSco/firecms.git",
11
- "main": "./dist/index.umd.js",
12
- "module": "./dist/index.es.js",
13
- "types": "./dist/index.d.ts",
14
- "source": "src/index.ts",
15
- "engines": {
16
- "node": ">=14"
17
- },
18
- "exports": {
19
- ".": {
20
- "import": "./dist/index.es.js",
21
- "require": "./dist/index.umd.js",
22
- "types": "./dist/index.d.ts"
23
- },
24
- "./package.json": "./package.json"
25
- },
26
- "keywords": [
27
- "firebase",
28
- "cms",
29
- "admin",
30
- "admin panel",
31
- "firebase panel",
32
- "firestore",
33
- "headless",
34
- "headless cms",
35
- "content manager"
36
- ],
37
- "scripts": {
38
- "watch": "vite build --watch",
39
- "build": "vite build && tsc --emitDeclarationOnly",
40
- "prepublishOnly": "run-s build",
41
- "createTag": "PACKAGE_VERSION=$(cat package.json | grep version | head -1 | awk -F: '{ print $2 }' | sed 's/[\",]//g' | tr -d '[[:space:]]') && git tag v$PACKAGE_VERSION && git push --tags",
42
- "test:lint": "eslint \"src/**\" --quiet",
43
- "test": "jest",
44
- "generateIcons": "ts-node --esm src/icons/generateIcons.ts"
45
- },
46
- "dependencies": {
47
- "@date-io/date-fns": "^2.17.0",
48
- "@fontsource/ibm-plex-mono": "^5.0.8",
49
- "@fontsource/roboto": "^5.0.8",
50
- "@hello-pangea/dnd": "^16.3.0",
51
- "@material-design-icons/font": "^0.14.13",
52
- "@radix-ui/react-checkbox": "^1.0.4",
53
- "@radix-ui/react-collapsible": "^1.0.3",
54
- "@radix-ui/react-dialog": "^1.0.5",
55
- "@radix-ui/react-dropdown-menu": "^2.0.6",
56
- "@radix-ui/react-popover": "^1.0.7",
57
- "@radix-ui/react-portal": "^1.0.4",
58
- "@radix-ui/react-scroll-area": "^1.0.5",
59
- "@radix-ui/react-select": "^1.2.2",
60
- "@radix-ui/react-switch": "^1.0.3",
61
- "@radix-ui/react-tabs": "^1.0.4",
62
- "@radix-ui/react-tooltip": "^1.0.7",
63
- "cmdk": "^0.2.0",
64
- "date-fns": "^2.30.0",
65
- "formik": "^2.4.5",
66
- "history": "^5.3.0",
67
- "js-search": "^2.0.1",
68
- "markdown-it": "^13.0.2",
69
- "notistack": "^3.0.1",
70
- "object-hash": "^3.0.0",
71
- "react-datepicker": "^4.21.0",
72
- "react-dropzone": "^14.2.3",
73
- "react-fast-compare": "^3.2.2",
74
- "react-image-file-resizer": "^0.4.8",
75
- "react-markdown-editor-lite": "^1.3.4",
76
- "react-transition-group": "^4.4.5",
77
- "react-use-measure": "^2.1.1",
78
- "react-window": "^1.8.9",
79
- "tailwind-merge": "^1.14.0",
80
- "typeface-rubik": "^1.1.13",
81
- "yup": "^0.32.11"
82
- },
83
- "peerDependencies": {
84
- "algoliasearch": "^4.13.0",
85
- "firebase": "^10.4.0",
86
- "react": "^18.2.0",
87
- "react-dom": "^18.2.0",
88
- "react-router": "^6.2.0",
89
- "react-router-dom": "^6.2.0"
90
- },
91
- "eslintConfig": {
92
- "extends": [
93
- "react-app",
94
- "react-app/jest"
95
- ]
96
- },
97
- "devDependencies": {
98
- "@jest/globals": "^29.7.0",
99
- "@testing-library/jest-dom": "^5.17.0",
100
- "@testing-library/react": "^14.0.0",
101
- "@testing-library/user-event": "^14.5.1",
102
- "@types/jest": "^29.5.6",
103
- "@types/node": "^18.18.7",
104
- "@types/object-hash": "^3.0.5",
105
- "@types/react": "^18.2.33",
106
- "@types/react-dom": "^18.2.14",
107
- "@types/react-measure": "^2.0.10",
108
- "@typescript-eslint/eslint-plugin": "^5.62.0",
109
- "@typescript-eslint/parser": "^5.62.0",
110
- "@vitejs/plugin-react": "^4.1.0",
111
- "algoliasearch": "^4.20.0",
112
- "cross-env": "^7.0.3",
113
- "eslint": "^8.52.0",
114
- "eslint-config-standard": "^17.1.0",
115
- "eslint-plugin-import": "^2.29.0",
116
- "eslint-plugin-n": "^15.7.0",
117
- "eslint-plugin-promise": "^6.1.1",
118
- "eslint-plugin-react": "^7.33.2",
119
- "eslint-plugin-react-hooks": "^4.6.0",
120
- "firebase": "^10.5.2",
121
- "jest": "^29.7.0",
122
- "npm-run-all": "^4.1.5",
123
- "react-router": "^6.17.0",
124
- "react-router-dom": "^6.17.0",
125
- "ts-jest": "^29.1.1",
126
- "ts-node": "^10.9.1",
127
- "tsd": "^0.28.1",
128
- "typescript": "^5.2.2",
129
- "vite": "^4.5.0"
130
- },
131
- "files": [
132
- "dist",
133
- "src"
134
- ],
135
- "gitHead": "7b74c47b5ea9f490bd0ba3d2b479108484a19411",
136
- "publishConfig": {
137
- "access": "public"
138
- }
24
+ "./package.json": "./package.json"
25
+ },
26
+ "keywords": [
27
+ "firebase",
28
+ "cms",
29
+ "admin",
30
+ "admin panel",
31
+ "firebase panel",
32
+ "firestore",
33
+ "headless",
34
+ "headless cms",
35
+ "content manager"
36
+ ],
37
+ "scripts": {
38
+ "watch": "vite build --watch",
39
+ "build": "vite build && tsc --emitDeclarationOnly",
40
+ "prepublishOnly": "run-s build",
41
+ "createTag": "PACKAGE_VERSION=$(cat package.json | grep version | head -1 | awk -F: '{ print $2 }' | sed 's/[\",]//g' | tr -d '[[:space:]]') && git tag v$PACKAGE_VERSION && git push --tags",
42
+ "test:lint": "eslint \"src/**\" --quiet",
43
+ "test": "jest",
44
+ "clean": "rm -rf dist && find ./src -name '*.js' -type f | xargs rm -f",
45
+ "generateIcons": "ts-node --esm src/icons/generateIcons.ts"
46
+ },
47
+ "dependencies": {
48
+ "@date-io/date-fns": "^2.17.0",
49
+ "@fontsource/ibm-plex-mono": "^5.0.8",
50
+ "@fontsource/roboto": "^5.0.8",
51
+ "@hello-pangea/dnd": "^16.3.0",
52
+ "@material-design-icons/font": "^0.14.13",
53
+ "@radix-ui/react-checkbox": "^1.0.4",
54
+ "@radix-ui/react-collapsible": "^1.0.3",
55
+ "@radix-ui/react-dialog": "^1.0.5",
56
+ "@radix-ui/react-dropdown-menu": "^2.0.6",
57
+ "@radix-ui/react-popover": "^1.0.7",
58
+ "@radix-ui/react-portal": "^1.0.4",
59
+ "@radix-ui/react-scroll-area": "^1.0.5",
60
+ "@radix-ui/react-select": "^1.2.2",
61
+ "@radix-ui/react-switch": "^1.0.3",
62
+ "@radix-ui/react-tabs": "^1.0.4",
63
+ "@radix-ui/react-tooltip": "^1.0.7",
64
+ "cmdk": "^0.2.0",
65
+ "date-fns": "^2.30.0",
66
+ "formik": "^2.4.5",
67
+ "history": "^5.3.0",
68
+ "js-search": "^2.0.1",
69
+ "markdown-it": "^13.0.2",
70
+ "notistack": "^3.0.1",
71
+ "object-hash": "^3.0.0",
72
+ "react-datepicker": "^4.21.0",
73
+ "react-dropzone": "^14.2.3",
74
+ "react-fast-compare": "^3.2.2",
75
+ "react-image-file-resizer": "^0.4.8",
76
+ "react-markdown-editor-lite": "^1.3.4",
77
+ "react-transition-group": "^4.4.5",
78
+ "react-use-measure": "^2.1.1",
79
+ "react-window": "^1.8.9",
80
+ "tailwind-merge": "^1.14.0",
81
+ "typeface-rubik": "^1.1.13",
82
+ "yup": "^0.32.11"
83
+ },
84
+ "peerDependencies": {
85
+ "algoliasearch": "^4.13.0",
86
+ "firebase": "^10.4.0",
87
+ "react": "^18.2.0",
88
+ "react-dom": "^18.2.0",
89
+ "react-router": "^6.2.0",
90
+ "react-router-dom": "^6.2.0"
91
+ },
92
+ "eslintConfig": {
93
+ "extends": [
94
+ "react-app",
95
+ "react-app/jest"
96
+ ]
97
+ },
98
+ "devDependencies": {
99
+ "@jest/globals": "^29.7.0",
100
+ "@testing-library/jest-dom": "^5.17.0",
101
+ "@testing-library/react": "^14.0.0",
102
+ "@testing-library/user-event": "^14.5.1",
103
+ "@types/jest": "^29.5.6",
104
+ "@types/node": "^18.18.7",
105
+ "@types/object-hash": "^3.0.5",
106
+ "@types/react": "^18.2.33",
107
+ "@types/react-dom": "^18.2.14",
108
+ "@types/react-measure": "^2.0.10",
109
+ "@typescript-eslint/eslint-plugin": "^5.62.0",
110
+ "@typescript-eslint/parser": "^5.62.0",
111
+ "@vitejs/plugin-react": "^4.1.0",
112
+ "algoliasearch": "^4.20.0",
113
+ "cross-env": "^7.0.3",
114
+ "eslint": "^8.52.0",
115
+ "eslint-config-standard": "^17.1.0",
116
+ "eslint-plugin-import": "^2.29.0",
117
+ "eslint-plugin-n": "^15.7.0",
118
+ "eslint-plugin-promise": "^6.1.1",
119
+ "eslint-plugin-react": "^7.33.2",
120
+ "eslint-plugin-react-hooks": "^4.6.0",
121
+ "firebase": "^10.5.2",
122
+ "jest": "^29.7.0",
123
+ "npm-run-all": "^4.1.5",
124
+ "react-router": "^6.17.0",
125
+ "react-router-dom": "^6.17.0",
126
+ "ts-jest": "^29.1.1",
127
+ "ts-node": "^10.9.1",
128
+ "tsd": "^0.28.1",
129
+ "typescript": "^5.2.2",
130
+ "vite": "^4.5.0"
131
+ },
132
+ "files": [
133
+ "dist",
134
+ "src"
135
+ ],
136
+ "gitHead": "efeb689af20f913978c975c8ab3f91718e43935b",
137
+ "publishConfig": {
138
+ "access": "public"
139
+ }
139
140
  }
@@ -27,7 +27,7 @@ export const BooleanSwitch = React.forwardRef(function BooleanSwitch({
27
27
  ref={ref}
28
28
  tabIndex={disabled ? -1 : undefined}
29
29
  onClick={disabled
30
- ? undefined
30
+ ? (e) => e.preventDefault()
31
31
  : (e) => {
32
32
  e.preventDefault();
33
33
  if (allowIndeterminate) {
@@ -54,12 +54,12 @@ export const BooleanSwitchWithLabel = function BooleanSwitchWithLabel({
54
54
  onBlur={onBlur}
55
55
  tabIndex={-1}
56
56
  className={cn(
57
- !invisible && fieldBackgroundMixin,
57
+ !invisible && fieldBackgroundMixin,
58
58
  !invisible && (disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin),
59
59
  disabled ? "cursor-default" : "cursor-pointer",
60
60
  "rounded-md relative max-w-full justify-between w-full box-border relative inline-flex items-center",
61
61
  !invisible && focus && !disabled ? focusedClasses : "",
62
- error ? "text-red-500 dark:text-red-600" : (focus ? "text-primary" : (!disabled ? "text-text-primary dark:text-text-primary-dark" : "text-text-secondary dark:text-text-secondary-dark")),
62
+ error ? "text-red-500 dark:text-red-600" : (focus && !disabled ? "text-primary" : (!disabled ? "text-text-primary dark:text-text-primary-dark" : "text-text-secondary dark:text-text-secondary-dark")),
63
63
  size === "small" ? "min-h-[40px]" : "min-h-[64px]",
64
64
  size === "small" ? "pl-2" : "pl-4",
65
65
  size === "small" ? "pr-4" : "pr-6",
@@ -13,7 +13,7 @@ export function CircularProgress({
13
13
 
14
14
  let sizeClasses = "";
15
15
  if (size === "small") {
16
- sizeClasses = "w-4 h-4 m-1";
16
+ sizeClasses = "w-4 h-4";
17
17
  } else if (size === "medium") {
18
18
  sizeClasses = "w-8 h-8 m-1";
19
19
  } else {
@@ -185,18 +185,6 @@ export function Select({
185
185
  </SelectPrimitive.Viewport>
186
186
  </SelectPrimitive.Content>
187
187
  </SelectPrimitive.Portal>
188
- {/*<SelectPrimitive.Portal>*/}
189
- {/* <SelectPrimitive.Content*/}
190
- {/* className={cn("z-50 relative border border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-800 p-2 rounded-lg shadow-lg ",*/}
191
- {/* // "overflow-auto"*/}
192
- {/* )}*/}
193
- {/* position={position}*/}
194
- {/* align={"center"}>*/}
195
- {/* <SelectPrimitive.Viewport>*/}
196
- {/* {children}*/}
197
- {/* </SelectPrimitive.Viewport>*/}
198
- {/* </SelectPrimitive.Content>*/}
199
- {/*</SelectPrimitive.Portal>*/}
200
188
  </SelectPrimitive.Root>
201
189
  );
202
190
  }
@@ -89,8 +89,7 @@ export function TextField<T extends string | number>({
89
89
  ? <TextareaAutosize
90
90
  {...inputProps as any}
91
91
  ref={inputRef}
92
-
93
- placeholder={placeholder}
92
+ placeholder={!focused && !hasValue ? undefined : placeholder}
94
93
  autoFocus={autoFocus}
95
94
  rows={rows}
96
95
  // onFocus={() => setFocused(true)}
@@ -119,10 +118,10 @@ export function TextField<T extends string | number>({
119
118
  label ? (size === "medium" ? "pt-[28px] pb-2" : "pt-4 pb-2") : "py-2",
120
119
  focused ? "text-text-primary dark:text-text-primary-dark" : "",
121
120
  endAdornment ? "pr-10" : "pr-3",
122
- inputClassName,
123
- disabled && "border border-transparent outline-none opacity-50 dark:opacity-50 text-gray-800 dark:text-gray-200"
121
+ disabled && "border border-transparent outline-none opacity-50 dark:opacity-50 text-gray-800 dark:text-gray-200",
122
+ inputClassName
124
123
  )}
125
- placeholder={placeholder}
124
+ placeholder={!focused && !hasValue ? undefined : placeholder}
126
125
  autoFocus={autoFocus}
127
126
  onFocus={() => setFocused(true)}
128
127
  onBlur={() => setFocused(false)}
@@ -150,7 +149,7 @@ export function TextField<T extends string | number>({
150
149
  className={cn(
151
150
  "pointer-events-none absolute",
152
151
  size === "medium" ? "top-1" : "-top-1",
153
- !error ? (focused ? "text-primary" : "text-text-secondary dark:text-text-secondary-dark") : "text-red-500 dark:text-red-600",
152
+ !error ? (focused ? "text-primary dark:text-primary" : "text-text-secondary dark:text-text-secondary-dark") : "text-red-500 dark:text-red-600",
154
153
  disabled ? "opacity-50" : "")}
155
154
  shrink={hasValue || focused}
156
155
  >
@@ -2,6 +2,7 @@ import * as React from "react";
2
2
  import { useLayoutEffect } from "react";
3
3
  import * as ReactDOM from "react-dom";
4
4
  import { debounce } from "../core/util/debounce";
5
+ import { cn } from "./util/cn";
5
6
 
6
7
  type State = {
7
8
  outerHeightStyle: number;
@@ -102,6 +103,7 @@ export const TextareaAutosize = React.forwardRef(function TextareaAutosize(
102
103
  getStyleValue(computedStyle.paddingBottom) + getStyleValue(computedStyle.paddingTop);
103
104
  const border =
104
105
  getStyleValue(computedStyle.borderBottomWidth) + getStyleValue(computedStyle.borderTopWidth);
106
+ const minHeight = getStyleValue(computedStyle.minHeight);
105
107
 
106
108
  // The height of the inner content
107
109
  const innerHeight = sizeReferenceElement.scrollHeight;
@@ -119,10 +121,11 @@ export const TextareaAutosize = React.forwardRef(function TextareaAutosize(
119
121
  if (maxRows) {
120
122
  outerHeight = Math.min(Number(maxRows) * singleRowHeight, outerHeight);
121
123
  }
122
- outerHeight = Math.max(outerHeight, singleRowHeight);
124
+ outerHeight = Math.max(outerHeight, singleRowHeight, minHeight);
123
125
 
124
126
  // Take the box sizing into account for applying this value as a style.
125
- const outerHeightStyle = outerHeight + (boxSizing === "border-box" ? padding + border : 0);
127
+ const outerHeightStyle = outerHeight + (!props.ignoreBoxSizing && boxSizing === "border-box" ? padding + border : 0);
128
+
126
129
  const overflow = Math.abs(outerHeight - innerHeight) <= 1;
127
130
 
128
131
  return {
@@ -274,7 +277,7 @@ export const TextareaAutosize = React.forwardRef(function TextareaAutosize(
274
277
  />
275
278
  <textarea
276
279
  aria-hidden
277
- className={props.shadowClassName}
280
+ className={cn(props.className, props.shadowClassName)}
278
281
  readOnly
279
282
  ref={shadowRef}
280
283
  tabIndex={-1}
@@ -327,8 +330,9 @@ export type TextareaAutosizeProps = Omit<React.InputHTMLAttributes<HTMLTextAreaE
327
330
  onResize?: (state: State) => void;
328
331
 
329
332
  autoFocus?: boolean;
330
- }
331
333
 
334
+ ignoreBoxSizing?: boolean;
335
+ }
332
336
 
333
337
  function useForkRef<Instance>(
334
338
  ...refs: Array<React.Ref<Instance> | undefined>
@@ -36,3 +36,5 @@ export * from "./Tooltip";
36
36
  export * from "./Typography";
37
37
  export * from "./Tabs";
38
38
  export * from "./Table";
39
+ export * from "./Popover";
40
+ export * from "./Badge";
@@ -53,7 +53,8 @@ export function FireCMS<UserType extends User>(props: FireCMSProps<UserType>) {
53
53
  plugins,
54
54
  onAnalyticsEvent,
55
55
  fields,
56
- entityViews
56
+ entityViews,
57
+ components
57
58
  } = props;
58
59
 
59
60
  useLocaleConfig(locale);
@@ -81,8 +82,9 @@ export function FireCMS<UserType extends User>(props: FireCMSProps<UserType>) {
81
82
  plugins,
82
83
  onAnalyticsEvent,
83
84
  entityViews: entityViews ?? [],
84
- fields: fields ?? {}
85
- }), [dateTimeFormat, locale, plugins, entityViews, fields]);
85
+ fields: fields ?? {},
86
+ components
87
+ }), [dateTimeFormat, locale, plugins, entityViews, fields, components]);
86
88
 
87
89
  if (navigation.navigationLoadingError) {
88
90
  return (
@@ -102,11 +102,13 @@ export const EntityCollectionTable = React.memo<EntityCollectionTableProps<any>>
102
102
  pageSize = 50,
103
103
  paginationEnabled,
104
104
  checkFilterCombination,
105
- setPopupCell
105
+ setPopupCell,
106
106
  },
107
107
  filterable = true,
108
108
  sortable = true,
109
- endAdornment
109
+ endAdornment,
110
+ additionalHeaderWidget,
111
+ AddColumnComponent
110
112
  }: EntityCollectionTableProps<M>) {
111
113
 
112
114
  const largeLayout = useLargeLayout();
@@ -291,7 +293,12 @@ export const EntityCollectionTable = React.memo<EntityCollectionTableProps<any>>
291
293
  custom: {
292
294
  resolvedProperty: property,
293
295
  disabled
294
- }
296
+ },
297
+ additionalHeaderWidget: (onHover) => additionalHeaderWidget?.({
298
+ property,
299
+ propertyKey: key,
300
+ onHover
301
+ })
295
302
  };
296
303
  });
297
304
 
@@ -408,6 +415,7 @@ export const EntityCollectionTable = React.memo<EntityCollectionTableProps<any>>
408
415
  }, [selectedEntityIds])}
409
416
  className="flex-grow"
410
417
  endAdornment={endAdornment}
418
+ AddColumnComponent={AddColumnComponent}
411
419
  />
412
420
 
413
421
  </div>
@@ -5,7 +5,9 @@ import {
5
5
  Entity,
6
6
  FilterValues,
7
7
  ResolvedProperties,
8
- SelectionController, TableController,
8
+ ResolvedProperty,
9
+ SelectionController,
10
+ TableController,
9
11
  User
10
12
  } from "../../../types";
11
13
  import { OnCellValueChange, UniqueFieldValidator } from "./types";
@@ -117,6 +119,14 @@ export type EntityCollectionTableProps<M extends Record<string, any>,
117
119
 
118
120
  endAdornment?: React.ReactNode;
119
121
 
122
+ additionalHeaderWidget?: (props: {
123
+ property: ResolvedProperty,
124
+ propertyKey: string,
125
+ onHover: boolean,
126
+ }) => React.ReactNode;
127
+
128
+ AddColumnComponent?: React.ComponentType;
129
+
120
130
  }
121
131
 
122
132
  export type GetPropertyForProps<M extends Record<string, any>> = {