@firecms/core 3.0.0-canary.39 → 3.0.0-canary.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@firecms/core",
3
3
  "type": "module",
4
- "version": "3.0.0-canary.39",
4
+ "version": "3.0.0-canary.40",
5
5
  "description": "Awesome Firebase/Firestore-based headless open-source CMS",
6
6
  "funding": {
7
7
  "url": "https://github.com/sponsors/firecmsco"
@@ -46,8 +46,8 @@
46
46
  "./package.json": "./package.json"
47
47
  },
48
48
  "dependencies": {
49
- "@firecms/formex": "^3.0.0-canary.39",
50
- "@firecms/ui": "^3.0.0-canary.39",
49
+ "@firecms/formex": "^3.0.0-canary.40",
50
+ "@firecms/ui": "^3.0.0-canary.40",
51
51
  "@fontsource/jetbrains-mono": "^5.0.19",
52
52
  "@fontsource/roboto": "^5.0.12",
53
53
  "@hello-pangea/dnd": "^16.5.0",
@@ -115,7 +115,7 @@
115
115
  "dist",
116
116
  "src"
117
117
  ],
118
- "gitHead": "8ed816e32d8f66d2bf0dffcbfceb569b48a3cc0d",
118
+ "gitHead": "40b01721ac260b6cce7f5d8a3a1d768410e7f20d",
119
119
  "publishConfig": {
120
120
  "access": "public"
121
121
  }
@@ -8,8 +8,13 @@ import { ModeController } from "./index";
8
8
  */
9
9
  export function useBuildModeController(): ModeController {
10
10
 
11
- const prefersDarkModeQuery = typeof window !== "undefined" &&
12
- window.matchMedia("(prefers-color-scheme: dark)");
11
+ const prefersDarkModeQuery = useCallback((): boolean => {
12
+ if (typeof window === "undefined")
13
+ return false;
14
+ const mediaQueryList = window.matchMedia("(prefers-color-scheme: dark)");
15
+ return mediaQueryList.matches;
16
+ }, []);
17
+
13
18
  const prefersDarkModeStorage: boolean | null = localStorage.getItem("prefers-dark-mode") != null ? localStorage.getItem("prefers-dark-mode") === "true" : null;
14
19
  const prefersDarkMode = prefersDarkModeStorage ?? prefersDarkModeQuery;
15
20
  const [mode, setMode] = useState<"light" | "dark">(prefersDarkMode ? "dark" : "light");
@@ -23,7 +28,7 @@ export function useBuildModeController(): ModeController {
23
28
  const setDarkMode = useCallback(() => {
24
29
  setMode("dark");
25
30
  setDocumentMode("dark");
26
- }, [prefersDarkModeQuery]);
31
+ }, []);
27
32
 
28
33
  const setLightMode = useCallback(() => {
29
34
  setMode("light");
@@ -37,14 +42,15 @@ export function useBuildModeController(): ModeController {
37
42
 
38
43
  const toggleMode = useCallback(() => {
39
44
 
45
+ const prefersDarkModeQueryResult = prefersDarkModeQuery();
40
46
  if (mode === "light") {
41
- if (!prefersDarkModeQuery)
47
+ if (!prefersDarkModeQueryResult)
42
48
  localStorage.setItem("prefers-dark-mode", "true");
43
49
  else
44
50
  localStorage.removeItem("prefers-dark-mode");
45
51
  setDarkMode();
46
52
  } else {
47
- if (prefersDarkModeQuery)
53
+ if (prefersDarkModeQueryResult)
48
54
  localStorage.setItem("prefers-dark-mode", "false");
49
55
  else
50
56
  localStorage.removeItem("prefers-dark-mode");
@@ -187,6 +187,8 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
187
187
  if (authController.initialLoading)
188
188
  return;
189
189
 
190
+ console.debug("Refreshing navigation");
191
+
190
192
  try {
191
193
 
192
194
  const [resolvedCollections = [], resolvedViews, resolvedAdminViews = []] = await Promise.all([
@@ -196,16 +198,23 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
196
198
  ]
197
199
  );
198
200
 
199
- if (
200
- !equal(collectionsRef.current, resolvedCollections) ||
201
- !equal(viewsRef.current, resolvedViews) ||
202
- !equal(adminViewsRef.current, resolvedAdminViews) ||
203
- !equal(topLevelNavigation, computeTopNavigation(resolvedCollections, resolvedViews, resolvedAdminViews, viewsOrder))
204
- ) {
201
+ let shouldUpdateTopLevelNav = false;
202
+ if (!areCollectionListsEqual(collectionsRef.current ?? [], resolvedCollections)) {
205
203
  collectionsRef.current = resolvedCollections;
204
+ shouldUpdateTopLevelNav = true;
205
+ }
206
+ if (!equal(viewsRef.current, resolvedViews)) {
206
207
  viewsRef.current = resolvedViews;
208
+ shouldUpdateTopLevelNav = true;
209
+ }
210
+ if (!equal(adminViewsRef.current, resolvedAdminViews)) {
207
211
  adminViewsRef.current = resolvedAdminViews;
208
- setTopLevelNavigation(computeTopNavigation(resolvedCollections ?? [], resolvedViews, resolvedAdminViews, viewsOrder));
212
+ shouldUpdateTopLevelNav = true;
213
+ }
214
+
215
+ const computedTopLevelNav = computeTopNavigation(resolvedCollections, resolvedViews, resolvedAdminViews, viewsOrder);
216
+ if (shouldUpdateTopLevelNav && !equal(topLevelNavigation, computedTopLevelNav)) {
217
+ setTopLevelNavigation(computedTopLevelNav);
209
218
  }
210
219
  } catch (e) {
211
220
  console.error(e);
@@ -475,3 +484,27 @@ function getGroup(collectionOrView: EntityCollection<any, any> | CMSView) {
475
484
  }
476
485
  return trimmed ?? "Views";
477
486
  }
487
+
488
+ function areCollectionListsEqual(a: EntityCollection[], b: EntityCollection[]) {
489
+ if (a.length !== b.length) {
490
+ return false;
491
+ }
492
+ const aSorted = a.sort((a, b) => a.id.localeCompare(b.id));
493
+ const bSorted = b.sort((a, b) => a.id.localeCompare(b.id));
494
+ return aSorted.every((value, index) => areCollectionsEqual(value, bSorted[index]));
495
+ }
496
+
497
+ function areCollectionsEqual(a: EntityCollection, b: EntityCollection) {
498
+ const {
499
+ subcollections: subcollectionsA,
500
+ ...restA
501
+ } = a;
502
+ const {
503
+ subcollections: subcollectionsB,
504
+ ...restB
505
+ } = b;
506
+ if (!areCollectionListsEqual(subcollectionsA ?? [], subcollectionsB ?? [])) {
507
+ return false;
508
+ }
509
+ return equal(restA, restB);
510
+ }
@@ -43,9 +43,9 @@ export const useBuildSideEntityController = (navigation: NavigationController,
43
43
  const panel = panelsFromUrl[i];
44
44
  setTimeout(() => {
45
45
  if (i === 0)
46
- sideDialogsController.replace(propsToSidePanel(panel, navigation, smallLayout));
46
+ sideDialogsController.replace(propsToSidePanel(panel, navigation.buildUrlCollectionPath, navigation.resolveAliasesFrom, smallLayout));
47
47
  else
48
- sideDialogsController.open(propsToSidePanel(panel, navigation, smallLayout))
48
+ sideDialogsController.open(propsToSidePanel(panel, navigation.buildUrlCollectionPath, navigation.resolveAliasesFrom, smallLayout))
49
49
  }, 1);
50
50
  }
51
51
  } else {
@@ -53,7 +53,7 @@ export const useBuildSideEntityController = (navigation: NavigationController,
53
53
  }
54
54
  initialised.current = true;
55
55
  }
56
- }, [location, navigation, sideDialogsController, smallLayout]);
56
+ }, [location, navigation.loading, navigation.isUrlCollectionPath, navigation.buildUrlCollectionPath, navigation.resolveAliasesFrom, sideDialogsController, smallLayout, navigation]);
57
57
 
58
58
  const close = useCallback(() => {
59
59
  sideDialogsController.close();
@@ -76,9 +76,9 @@ export const useBuildSideEntityController = (navigation: NavigationController,
76
76
  sideDialogsController.open(propsToSidePanel({
77
77
  selectedSubPath: defaultSelectedView,
78
78
  ...props,
79
- }, navigation, smallLayout));
79
+ }, navigation.buildUrlCollectionPath, navigation.resolveAliasesFrom, smallLayout));
80
80
 
81
- }, [sideDialogsController, navigation, smallLayout]);
81
+ }, [sideDialogsController, navigation.buildUrlCollectionPath, navigation.resolveAliasesFrom, smallLayout]);
82
82
 
83
83
  const replace = useCallback((props: EntitySidePanelProps<any>) => {
84
84
 
@@ -86,9 +86,9 @@ export const useBuildSideEntityController = (navigation: NavigationController,
86
86
  throw Error("If you want to copy an entity you need to provide an entityId");
87
87
  }
88
88
 
89
- sideDialogsController.replace(propsToSidePanel(props, navigation, smallLayout));
89
+ sideDialogsController.replace(propsToSidePanel(props, navigation.buildUrlCollectionPath, navigation.resolveAliasesFrom, smallLayout));
90
90
 
91
- }, [navigation, sideDialogsController, smallLayout]);
91
+ }, [navigation.buildUrlCollectionPath, navigation.resolveAliasesFrom, sideDialogsController, smallLayout]);
92
92
 
93
93
  return {
94
94
  close,
@@ -149,14 +149,17 @@ export function buildSidePanelsFromUrl(path: string, collections: EntityCollecti
149
149
  return sidePanels;
150
150
  }
151
151
 
152
- const propsToSidePanel = (props: EntitySidePanelProps<any>, navigation: NavigationController, smallLayout: boolean): SideDialogPanelProps => {
152
+ const propsToSidePanel = (props: EntitySidePanelProps<any>,
153
+ buildUrlCollectionPath: (path: string) => string,
154
+ resolveAliasesFrom: (pathWithAliases: string) => string,
155
+ smallLayout: boolean): SideDialogPanelProps => {
153
156
 
154
157
  const collectionPath = removeInitialAndTrailingSlashes(props.path);
155
158
 
156
159
  const newPath = props.entityId
157
- ? navigation.buildUrlCollectionPath(`${collectionPath}/${props.entityId}/${props.selectedSubPath || ""}`)
158
- : navigation.buildUrlCollectionPath(`${collectionPath}#${NEW_URL_HASH}`);
159
- const resolvedPath = navigation.resolveAliasesFrom(props.path);
160
+ ? buildUrlCollectionPath(`${collectionPath}/${props.entityId}/${props.selectedSubPath || ""}`)
161
+ : buildUrlCollectionPath(`${collectionPath}#${NEW_URL_HASH}`);
162
+ const resolvedPath = resolveAliasesFrom(props.path);
160
163
 
161
164
  const resolvedPanelProps: EntitySidePanelProps<any> = {
162
165
  ...props,
@@ -167,7 +170,7 @@ const propsToSidePanel = (props: EntitySidePanelProps<any>, navigation: Navigati
167
170
  key: `${props.path}/${props.entityId}`,
168
171
  component: <EntitySidePanel {...resolvedPanelProps}/>,
169
172
  urlPath: newPath,
170
- parentUrlPath: navigation.buildUrlCollectionPath(collectionPath),
173
+ parentUrlPath: buildUrlCollectionPath(collectionPath),
171
174
  width: getEntityViewWidth(props, smallLayout),
172
175
  onClose: props.onClose
173
176
  });