@firecms/core 3.0.0-canary.248 → 3.0.0-canary.249

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 (45) hide show
  1. package/dist/components/HomePage/DefaultHomePage.d.ts +2 -15
  2. package/dist/components/HomePage/HomePageDnD.d.ts +76 -0
  3. package/dist/components/HomePage/NavigationCard.d.ts +3 -1
  4. package/dist/components/HomePage/NavigationCardBinding.d.ts +3 -2
  5. package/dist/components/HomePage/NavigationGroup.d.ts +7 -1
  6. package/dist/components/HomePage/RenameGroupDialog.d.ts +9 -0
  7. package/dist/core/field_configs.d.ts +1 -1
  8. package/dist/form/field_bindings/ReferenceAsStringFieldBinding.d.ts +9 -0
  9. package/dist/form/index.d.ts +1 -0
  10. package/dist/hooks/useBuildNavigationController.d.ts +51 -2
  11. package/dist/index.es.js +1726 -778
  12. package/dist/index.es.js.map +1 -1
  13. package/dist/index.umd.js +1723 -775
  14. package/dist/index.umd.js.map +1 -1
  15. package/dist/types/analytics.d.ts +1 -1
  16. package/dist/types/collections.d.ts +3 -0
  17. package/dist/types/navigation.d.ts +20 -4
  18. package/dist/types/plugins.d.ts +12 -0
  19. package/dist/types/properties.d.ts +7 -0
  20. package/dist/types/property_config.d.ts +1 -1
  21. package/dist/util/icons.d.ts +1 -1
  22. package/package.json +5 -5
  23. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +25 -3
  24. package/src/components/HomePage/DefaultHomePage.tsx +476 -157
  25. package/src/components/HomePage/FavouritesView.tsx +3 -3
  26. package/src/components/HomePage/HomePageDnD.tsx +613 -0
  27. package/src/components/HomePage/NavigationCard.tsx +47 -38
  28. package/src/components/HomePage/NavigationCardBinding.tsx +10 -6
  29. package/src/components/HomePage/NavigationGroup.tsx +63 -29
  30. package/src/components/HomePage/RenameGroupDialog.tsx +113 -0
  31. package/src/core/DefaultDrawer.tsx +8 -8
  32. package/src/core/DrawerNavigationItem.tsx +1 -1
  33. package/src/core/field_configs.tsx +15 -1
  34. package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +135 -0
  35. package/src/form/field_bindings/RepeatFieldBinding.tsx +0 -1
  36. package/src/form/index.tsx +1 -0
  37. package/src/hooks/useBuildNavigationController.tsx +273 -84
  38. package/src/preview/PropertyPreview.tsx +14 -0
  39. package/src/types/analytics.ts +3 -0
  40. package/src/types/collections.ts +3 -0
  41. package/src/types/navigation.ts +27 -5
  42. package/src/types/plugins.tsx +15 -0
  43. package/src/types/properties.ts +8 -0
  44. package/src/types/property_config.tsx +1 -0
  45. package/src/util/icons.tsx +7 -3
package/dist/index.es.js CHANGED
@@ -2,11 +2,11 @@ import { jsx, Fragment, jsxs } from "react/jsx-runtime";
2
2
  import { c } from "react-compiler-runtime";
3
3
  import * as React from "react";
4
4
  import React__default, { useRef, useEffect, useContext, useCallback, useMemo, useState, createElement, createRef, createContext, forwardRef, useLayoutEffect, useDeferredValue } from "react";
5
- import { getColorSchemeForSeed, CHIP_COLORS, CircleIcon, FunctionsIcon, iconKeys, coolIconKeys, Icon, Tooltip, ErrorIcon, Typography, IconButton, ContentCopyIcon, OpenInNewIcon, DescriptionIcon, cls, Skeleton, Chip, defaultBorderMixin, KeyboardTabIcon, Checkbox, Markdown, TextareaAutosize, focusedDisabled, MultiSelect, MultiSelectItem, Select, SelectItem, BooleanSwitch, DateTimeField, paperMixin, EditIcon, DoNotDisturbOnIcon, Menu, MoreVertIcon, MenuItem, CircularProgress, SearchBar, Badge, ArrowUpwardIcon, Popover, FilterListIcon, Button, CenteredView, AssignmentIcon, Label, CloseIcon, TextField, BooleanSwitchWithLabel, useOutsideAlerter, Dialog, DialogTitle, DialogContent, DialogActions, FileCopyIcon, DeleteIcon, AddIcon, ExpandablePanel, ArrowForwardIcon, Card, cardMixin, cardClickableMixin, StarIcon, Collapse, Container, LoadingButton, Alert, CheckIcon, NotesIcon, InfoIcon, fieldBackgroundMixin, RemoveIcon, fieldBackgroundDisabledMixin, fieldBackgroundHoverMixin, ArrowDropDownIcon, FilterListOffIcon, SearchIcon, Avatar, DarkModeIcon, LightModeIcon, BrightnessMediumIcon, LogoutIcon, HandleIcon, KeyboardArrowUpIcon, KeyboardArrowDownIcon, debounce, Sheet, Tab, Tabs, CodeIcon, OpenInFullIcon, ShortTextIcon, SubjectIcon, FormatQuoteIcon, HttpIcon, MailIcon, FlagIcon, ListIcon, ListAltIcon, NumbersIcon, FormatListNumberedIcon, UploadFileIcon, DriveFolderUploadIcon, LinkIcon, AddLinkIcon, ScheduleIcon, BallotIcon, RepeatIcon, ViewStreamIcon, MenuIcon, ChevronLeftIcon } from "@firecms/ui";
5
+ import { getColorSchemeForSeed, CHIP_COLORS, CircleIcon, FunctionsIcon, iconKeys, coolIconKeys, Icon, Tooltip, ErrorIcon, Typography, IconButton, ContentCopyIcon, OpenInNewIcon, DescriptionIcon, cls, Skeleton, Chip, defaultBorderMixin, KeyboardTabIcon, Checkbox, Markdown, TextareaAutosize, focusedDisabled, MultiSelect, MultiSelectItem, Select, SelectItem, BooleanSwitch, DateTimeField, paperMixin, EditIcon, DoNotDisturbOnIcon, Menu, MoreVertIcon, MenuItem, CircularProgress, SearchBar, Badge, ArrowUpwardIcon, Popover, FilterListIcon, Button, CenteredView, AssignmentIcon, Label, CloseIcon, TextField, BooleanSwitchWithLabel, useOutsideAlerter, Dialog, DialogTitle, DialogContent, DialogActions, FileCopyIcon, DeleteIcon, AddIcon, Collapse, StarIcon, ArrowForwardIcon, Card, cardMixin, cardClickableMixin, Container, LoadingButton, Alert, CheckIcon, NotesIcon, InfoIcon, ExpandablePanel, fieldBackgroundMixin, RemoveIcon, fieldBackgroundDisabledMixin, fieldBackgroundHoverMixin, ArrowDropDownIcon, FilterListOffIcon, SearchIcon, Avatar, DarkModeIcon, LightModeIcon, BrightnessMediumIcon, LogoutIcon, HandleIcon, KeyboardArrowUpIcon, KeyboardArrowDownIcon, debounce, Sheet, Tab, Tabs, CodeIcon, OpenInFullIcon, ShortTextIcon, SubjectIcon, FormatQuoteIcon, HttpIcon, MailIcon, FlagIcon, ListIcon, ListAltIcon, NumbersIcon, FormatListNumberedIcon, UploadFileIcon, DriveFolderUploadIcon, LinkIcon, AddLinkIcon, ScheduleIcon, BallotIcon, RepeatIcon, ViewStreamIcon, MenuIcon, ChevronLeftIcon } from "@firecms/ui";
6
6
  import { SnackbarProvider as SnackbarProvider$1, useSnackbar } from "notistack";
7
7
  import hash from "object-hash";
8
8
  import { getIn, useFormex, useCreateFormex, Formex, setIn, Field } from "@firecms/formex";
9
- import { Link, useNavigate, useLocation, NavLink, Routes, Route, createBrowserRouter, RouterProvider } from "react-router-dom";
9
+ import { useNavigate, useLocation, Link, NavLink, Routes, Route, createBrowserRouter, RouterProvider } from "react-router-dom";
10
10
  import Fuse from "fuse.js";
11
11
  import equal from "react-fast-compare";
12
12
  import { format } from "date-fns";
@@ -14,10 +14,10 @@ import * as locales from "date-fns/locale";
14
14
  import useMeasure from "react-use-measure";
15
15
  import * as yup from "yup";
16
16
  import { FixedSizeList } from "react-window";
17
- import { useSensors, useSensor, PointerSensor, KeyboardSensor, DndContext, closestCenter } from "@dnd-kit/core";
18
- import { restrictToVerticalAxis } from "@dnd-kit/modifiers";
19
- import { sortableKeyboardCoordinates, SortableContext, horizontalListSortingStrategy, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
17
+ import { useDroppable, useSensor, MouseSensor, TouchSensor, KeyboardSensor, useSensors, closestCenter, pointerWithin, closestCorners, getFirstCollision, rectIntersection, useDndMonitor, DndContext, MeasuringStrategy, DragOverlay, PointerSensor } from "@dnd-kit/core";
18
+ import { useSortable, defaultAnimateLayoutChanges, SortableContext, rectSortingStrategy, arrayMove as arrayMove$1, verticalListSortingStrategy, sortableKeyboardCoordinates, horizontalListSortingStrategy } from "@dnd-kit/sortable";
20
19
  import { CSS } from "@dnd-kit/utilities";
20
+ import { restrictToVerticalAxis, restrictToWindowEdges } from "@dnd-kit/modifiers";
21
21
  import { useDropzone } from "react-dropzone";
22
22
  import Resizer from "react-image-file-resizer";
23
23
  import { FireCMSEditor } from "@firecms/editor";
@@ -3185,16 +3185,16 @@ function hashString(str) {
3185
3185
  }
3186
3186
  return Math.abs(hash2);
3187
3187
  }
3188
- function getIcon(iconKey, className, color) {
3188
+ function getIcon(iconKey, className, color, size) {
3189
3189
  if (!iconKey) return void 0;
3190
3190
  iconKey = slugify(iconKey);
3191
3191
  if (!(iconKey in iconKeysMap)) {
3192
3192
  return void 0;
3193
3193
  }
3194
- return iconKey in iconKeysMap ? /* @__PURE__ */ jsx(Icon, { iconKey, size: "medium", className, color }) : void 0;
3194
+ return iconKey in iconKeysMap ? /* @__PURE__ */ jsx(Icon, { iconKey, size, className, color }) : void 0;
3195
3195
  }
3196
3196
  const IconForView = React__default.memo(function IconForView2(t0) {
3197
- const $ = c(14);
3197
+ const $ = c(15);
3198
3198
  const {
3199
3199
  collectionOrView,
3200
3200
  className,
@@ -3213,14 +3213,15 @@ const IconForView = React__default.memo(function IconForView2(t0) {
3213
3213
  return t22;
3214
3214
  }
3215
3215
  let t2;
3216
- if ($[1] !== className || $[2] !== collectionOrView.icon || $[3] !== color) {
3217
- t2 = getIcon(collectionOrView.icon, className, color);
3216
+ if ($[1] !== className || $[2] !== collectionOrView.icon || $[3] !== color || $[4] !== size) {
3217
+ t2 = getIcon(collectionOrView.icon, className, color, size);
3218
3218
  $[1] = className;
3219
3219
  $[2] = collectionOrView.icon;
3220
3220
  $[3] = color;
3221
- $[4] = t2;
3221
+ $[4] = size;
3222
+ $[5] = t2;
3222
3223
  } else {
3223
- t2 = $[4];
3224
+ t2 = $[5];
3224
3225
  }
3225
3226
  const icon = t2;
3226
3227
  if (collectionOrView?.icon && icon) {
@@ -3228,12 +3229,12 @@ const IconForView = React__default.memo(function IconForView2(t0) {
3228
3229
  }
3229
3230
  const t3 = ("singularName" in collectionOrView ? collectionOrView.singularName : void 0) ?? collectionOrView.name;
3230
3231
  let t4;
3231
- if ($[5] !== t3) {
3232
+ if ($[6] !== t3) {
3232
3233
  t4 = slugify(t3);
3233
- $[5] = t3;
3234
- $[6] = t4;
3234
+ $[6] = t3;
3235
+ $[7] = t4;
3235
3236
  } else {
3236
- t4 = $[6];
3237
+ t4 = $[7];
3237
3238
  }
3238
3239
  let slugName = t4;
3239
3240
  let key;
@@ -3242,12 +3243,12 @@ const IconForView = React__default.memo(function IconForView2(t0) {
3242
3243
  }
3243
3244
  if (!key) {
3244
3245
  let t52;
3245
- if ($[7] !== collectionOrView.path) {
3246
+ if ($[8] !== collectionOrView.path) {
3246
3247
  t52 = slugify(collectionOrView.path);
3247
- $[7] = collectionOrView.path;
3248
- $[8] = t52;
3248
+ $[8] = collectionOrView.path;
3249
+ $[9] = t52;
3249
3250
  } else {
3250
- t52 = $[8];
3251
+ t52 = $[9];
3251
3252
  }
3252
3253
  slugName = t52;
3253
3254
  if (slugName in iconKeysMap) {
@@ -3259,15 +3260,15 @@ const IconForView = React__default.memo(function IconForView2(t0) {
3259
3260
  key = coolIconKeys[hashString(collectionOrView.path) % iconsCount];
3260
3261
  }
3261
3262
  let t5;
3262
- if ($[9] !== className || $[10] !== color || $[11] !== key || $[12] !== size) {
3263
+ if ($[10] !== className || $[11] !== color || $[12] !== key || $[13] !== size) {
3263
3264
  t5 = /* @__PURE__ */ jsx(Icon, { iconKey: key, size, className, color });
3264
- $[9] = className;
3265
- $[10] = color;
3266
- $[11] = key;
3267
- $[12] = size;
3268
- $[13] = t5;
3265
+ $[10] = className;
3266
+ $[11] = color;
3267
+ $[12] = key;
3268
+ $[13] = size;
3269
+ $[14] = t5;
3269
3270
  } else {
3270
- t5 = $[13];
3271
+ t5 = $[14];
3271
3272
  }
3272
3273
  return t5;
3273
3274
  }, (prevProps, nextProps) => {
@@ -4144,7 +4145,7 @@ function useCollectionFetch(t0) {
4144
4145
  }
4145
4146
  setDataLoading(false);
4146
4147
  setDataLoadingError(void 0);
4147
- setData(entities.map(_temp$s));
4148
+ setData(entities.map(_temp$r));
4148
4149
  setNoMoreToLoad(!itemCount || entities.length < itemCount);
4149
4150
  };
4150
4151
  const onError = (error) => {
@@ -4177,7 +4178,7 @@ function useCollectionFetch(t0) {
4177
4178
  orderBy: sortByProperty,
4178
4179
  order: currentSort
4179
4180
  }).then(onEntitiesUpdate).catch(onError);
4180
- return _temp2$e;
4181
+ return _temp2$d;
4181
4182
  }
4182
4183
  };
4183
4184
  $[4] = collection;
@@ -4225,9 +4226,9 @@ function useCollectionFetch(t0) {
4225
4226
  }
4226
4227
  return t5;
4227
4228
  }
4228
- function _temp2$e() {
4229
+ function _temp2$d() {
4229
4230
  }
4230
- function _temp$s(e_0) {
4231
+ function _temp$r(e_0) {
4231
4232
  return {
4232
4233
  ...e_0
4233
4234
  };
@@ -4292,7 +4293,7 @@ function useEntityFetch(t0) {
4292
4293
  setEntity(CACHE[`${path}/${entityId}`]);
4293
4294
  setDataLoading(false);
4294
4295
  setDataLoadingError(void 0);
4295
- return _temp$r;
4296
+ return _temp$q;
4296
4297
  } else {
4297
4298
  if (entityId && path && collection) {
4298
4299
  if (dataSource.listenEntity) {
@@ -4311,11 +4312,11 @@ function useEntityFetch(t0) {
4311
4312
  databaseId,
4312
4313
  collection
4313
4314
  }).then(onEntityUpdate).catch(onError);
4314
- return _temp2$d;
4315
+ return _temp2$c;
4315
4316
  }
4316
4317
  } else {
4317
4318
  onEntityUpdate(void 0);
4318
- return _temp3$5;
4319
+ return _temp3$4;
4319
4320
  }
4320
4321
  }
4321
4322
  };
@@ -4356,11 +4357,11 @@ function useEntityFetch(t0) {
4356
4357
  }
4357
4358
  return t5;
4358
4359
  }
4359
- function _temp3$5() {
4360
+ function _temp3$4() {
4360
4361
  }
4361
- function _temp2$d() {
4362
+ function _temp2$c() {
4362
4363
  }
4363
- function _temp$r() {
4364
+ function _temp$q() {
4364
4365
  }
4365
4366
  async function saveEntityWithCallbacks({
4366
4367
  collection,
@@ -4944,7 +4945,7 @@ function ImagePreview(t0) {
4944
4945
  }
4945
4946
  let t9;
4946
4947
  if ($[16] !== url) {
4947
- t9 = /* @__PURE__ */ jsx(Tooltip, { title: "Open image in new tab", side: "bottom", children: /* @__PURE__ */ jsx(IconButton, { className: "invisible group-hover:visible", variant: "filled", component: "a", href: url, rel: "noopener noreferrer", target: "_blank", size: "smallest", onClick: _temp$q, children: t8 }) });
4948
+ t9 = /* @__PURE__ */ jsx(Tooltip, { title: "Open image in new tab", side: "bottom", children: /* @__PURE__ */ jsx(IconButton, { className: "invisible group-hover:visible", variant: "filled", component: "a", href: url, rel: "noopener noreferrer", target: "_blank", size: "smallest", onClick: _temp$p, children: t8 }) });
4948
4949
  $[16] = url;
4949
4950
  $[17] = t9;
4950
4951
  } else {
@@ -4978,7 +4979,7 @@ function ImagePreview(t0) {
4978
4979
  }
4979
4980
  return t11;
4980
4981
  }
4981
- function _temp$q(e_0) {
4982
+ function _temp$p(e_0) {
4982
4983
  return e_0.stopPropagation();
4983
4984
  }
4984
4985
  function UrlComponentPreview(t0) {
@@ -5011,7 +5012,7 @@ function UrlComponentPreview(t0) {
5011
5012
  }
5012
5013
  let t3;
5013
5014
  if ($[2] !== url) {
5014
- t3 = /* @__PURE__ */ jsxs("a", { className: "flex gap-4 break-words items-center font-medium text-primary visited:text-primary dark:visited:text-primary dark:text-primary", href: url, rel: "noopener noreferrer", onMouseDown: _temp$p, target: "_blank", children: [
5015
+ t3 = /* @__PURE__ */ jsxs("a", { className: "flex gap-4 break-words items-center font-medium text-primary visited:text-primary dark:visited:text-primary dark:text-primary", href: url, rel: "noopener noreferrer", onMouseDown: _temp$o, target: "_blank", children: [
5015
5016
  t2,
5016
5017
  url
5017
5018
  ] });
@@ -5114,7 +5115,7 @@ function UrlComponentPreview(t0) {
5114
5115
  }
5115
5116
  let t7;
5116
5117
  if ($[24] !== t4 || $[25] !== t6 || $[26] !== url) {
5117
- t7 = /* @__PURE__ */ jsxs("a", { href: url, rel: "noopener noreferrer", target: "_blank", onClick: _temp2$c, className: "flex flex-col items-center justify-center", style: t4, children: [
5118
+ t7 = /* @__PURE__ */ jsxs("a", { href: url, rel: "noopener noreferrer", target: "_blank", onClick: _temp2$b, className: "flex flex-col items-center justify-center", style: t4, children: [
5118
5119
  t5,
5119
5120
  t6
5120
5121
  ] });
@@ -5139,10 +5140,10 @@ function UrlComponentPreview(t0) {
5139
5140
  }
5140
5141
  }
5141
5142
  }
5142
- function _temp2$c(e_0) {
5143
+ function _temp2$b(e_0) {
5143
5144
  return e_0.stopPropagation();
5144
5145
  }
5145
- function _temp$p(e) {
5146
+ function _temp$o(e) {
5146
5147
  e.preventDefault();
5147
5148
  }
5148
5149
  function VideoPreview(t0) {
@@ -5276,7 +5277,7 @@ function SkeletonPropertyComponent(t0) {
5276
5277
  if (Array.isArray(arrayProperty.of)) {
5277
5278
  let t1;
5278
5279
  if ($[6] !== arrayProperty.of) {
5279
- t1 = arrayProperty.of.map(_temp$o);
5280
+ t1 = arrayProperty.of.map(_temp$n);
5280
5281
  $[6] = arrayProperty.of;
5281
5282
  $[7] = t1;
5282
5283
  } else {
@@ -5414,7 +5415,7 @@ function SkeletonPropertyComponent(t0) {
5414
5415
  }
5415
5416
  return content || null;
5416
5417
  }
5417
- function _temp$o(p, i) {
5418
+ function _temp$n(p, i) {
5418
5419
  return renderGenericArrayCell(p, i);
5419
5420
  }
5420
5421
  function renderMap(property, size) {
@@ -6596,7 +6597,7 @@ function KeyValuePreview(t0) {
6596
6597
  }
6597
6598
  let t1;
6598
6599
  if ($[1] !== value) {
6599
- t1 = Object.entries(value).map(_temp$n);
6600
+ t1 = Object.entries(value).map(_temp$m);
6600
6601
  $[1] = value;
6601
6602
  $[2] = t1;
6602
6603
  } else {
@@ -6612,7 +6613,7 @@ function KeyValuePreview(t0) {
6612
6613
  }
6613
6614
  return t2;
6614
6615
  }
6615
- function _temp$n(t0) {
6616
+ function _temp$m(t0) {
6616
6617
  const [key, childValue] = t0;
6617
6618
  return /* @__PURE__ */ jsxs("div", { className: cls(defaultBorderMixin, "last:border-b-0 border-b"), children: [
6618
6619
  /* @__PURE__ */ jsxs("div", { className: "flex flex-row pt-0.5 pb-0.5 gap-2", children: [
@@ -6746,7 +6747,7 @@ function NumberPropertyPreview(t0) {
6746
6747
  }
6747
6748
  }
6748
6749
  const PropertyPreview = React__default.memo(function PropertyPreview2(props) {
6749
- const $ = c(30);
6750
+ const $ = c(31);
6750
6751
  const authController = useAuthController();
6751
6752
  const customizationController = useCustomizationController();
6752
6753
  let content;
@@ -6845,7 +6846,22 @@ const PropertyPreview = React__default.memo(function PropertyPreview2(props) {
6845
6846
  }
6846
6847
  content = t02;
6847
6848
  } else {
6848
- content = /* @__PURE__ */ jsx(StringPropertyPreview, { ...props, property: stringProperty, value });
6849
+ if (stringProperty.reference) {
6850
+ if (typeof stringProperty.reference.path === "string") {
6851
+ content = /* @__PURE__ */ jsx(ReferencePreview, { disabled: !stringProperty.reference.path, previewProperties: stringProperty.reference.previewProperties, includeId: stringProperty.reference.includeId, includeEntityLink: stringProperty.reference.includeEntityLink, size: props.size, reference: new EntityReference(value, stringProperty.reference.path) });
6852
+ } else {
6853
+ let t02;
6854
+ if ($[23] === Symbol.for("react.memo_cache_sentinel")) {
6855
+ t02 = /* @__PURE__ */ jsx(EmptyValue, {});
6856
+ $[23] = t02;
6857
+ } else {
6858
+ t02 = $[23];
6859
+ }
6860
+ content = t02;
6861
+ }
6862
+ } else {
6863
+ content = /* @__PURE__ */ jsx(StringPropertyPreview, { ...props, property: stringProperty, value });
6864
+ }
6849
6865
  }
6850
6866
  }
6851
6867
  }
@@ -6904,12 +6920,12 @@ const PropertyPreview = React__default.memo(function PropertyPreview2(props) {
6904
6920
  if (property.dataType === "date") {
6905
6921
  if (value instanceof Date) {
6906
6922
  let t02;
6907
- if ($[23] !== value) {
6923
+ if ($[24] !== value) {
6908
6924
  t02 = /* @__PURE__ */ jsx(DatePreview, { date: value });
6909
- $[23] = value;
6910
- $[24] = t02;
6925
+ $[24] = value;
6926
+ $[25] = t02;
6911
6927
  } else {
6912
- t02 = $[24];
6928
+ t02 = $[25];
6913
6929
  }
6914
6930
  content = t02;
6915
6931
  } else {
@@ -6925,11 +6941,11 @@ const PropertyPreview = React__default.memo(function PropertyPreview2(props) {
6925
6941
  }
6926
6942
  } else {
6927
6943
  let t02;
6928
- if ($[25] === Symbol.for("react.memo_cache_sentinel")) {
6944
+ if ($[26] === Symbol.for("react.memo_cache_sentinel")) {
6929
6945
  t02 = /* @__PURE__ */ jsx(EmptyValue, {});
6930
- $[25] = t02;
6946
+ $[26] = t02;
6931
6947
  } else {
6932
- t02 = $[25];
6948
+ t02 = $[26];
6933
6949
  }
6934
6950
  content = t02;
6935
6951
  }
@@ -6949,12 +6965,12 @@ const PropertyPreview = React__default.memo(function PropertyPreview2(props) {
6949
6965
  }
6950
6966
  } else {
6951
6967
  let t02;
6952
- if ($[26] !== value) {
6968
+ if ($[27] !== value) {
6953
6969
  t02 = JSON.stringify(value);
6954
- $[26] = value;
6955
- $[27] = t02;
6970
+ $[27] = value;
6971
+ $[28] = t02;
6956
6972
  } else {
6957
- t02 = $[27];
6973
+ t02 = $[28];
6958
6974
  }
6959
6975
  content = t02;
6960
6976
  }
@@ -6982,12 +6998,12 @@ const PropertyPreview = React__default.memo(function PropertyPreview2(props) {
6982
6998
  content = $[10];
6983
6999
  }
6984
7000
  let t0;
6985
- if ($[28] !== content) {
7001
+ if ($[29] !== content) {
6986
7002
  t0 = content === void 0 || content === null || Array.isArray(content) && content.length === 0 ? /* @__PURE__ */ jsx(EmptyValue, {}) : content;
6987
- $[28] = content;
6988
- $[29] = t0;
7003
+ $[29] = content;
7004
+ $[30] = t0;
6989
7005
  } else {
6990
- t0 = $[29];
7006
+ t0 = $[30];
6991
7007
  }
6992
7008
  return t0;
6993
7009
  }, equal);
@@ -7365,7 +7381,7 @@ function VirtualTableSelect(props) {
7365
7381
  console.trace("onChange");
7366
7382
  if (valueType === "number") {
7367
7383
  if (multiple) {
7368
- const newValue = updatedValue.map(_temp$m);
7384
+ const newValue = updatedValue.map(_temp$l);
7369
7385
  updateValue(newValue);
7370
7386
  } else {
7371
7387
  updateValue(parseFloat(updatedValue));
@@ -7402,7 +7418,7 @@ function VirtualTableSelect(props) {
7402
7418
  const renderValue = t3;
7403
7419
  let t4;
7404
7420
  if ($[10] !== disabled || $[11] !== enumValues || $[12] !== internalValue || $[13] !== multiple || $[14] !== onChange || $[15] !== renderValue || $[16] !== small || $[17] !== validValue) {
7405
- t4 = multiple ? /* @__PURE__ */ jsx(MultiSelect, { inputRef: ref, className: "w-full h-full p-0 bg-transparent", position: "item-aligned", disabled, includeClear: false, useChips: false, value: validValue ? internalValue.map(_temp2$b) : [], onValueChange: onChange, children: enumValues?.map((enumConfig) => /* @__PURE__ */ jsx(MultiSelectItem, { value: String(enumConfig.id), children: /* @__PURE__ */ jsx(EnumValuesChip, { enumKey: enumConfig.id, enumValues, size: small ? "small" : "medium" }) }, enumConfig.id)) }) : /* @__PURE__ */ jsx(Select, { inputRef: ref, size: "large", fullWidth: true, className: "w-full h-full p-0 bg-transparent", position: "item-aligned", disabled, padding: false, value: validValue ? internalValue?.toString() : "", onValueChange: onChange, renderValue, children: enumValues?.map((enumConfig_0) => /* @__PURE__ */ jsx(SelectItem, { value: String(enumConfig_0.id), children: /* @__PURE__ */ jsx(EnumValuesChip, { enumKey: enumConfig_0.id, enumValues, size: small ? "small" : "medium" }) }, enumConfig_0.id)) });
7421
+ t4 = multiple ? /* @__PURE__ */ jsx(MultiSelect, { inputRef: ref, className: "w-full h-full p-0 bg-transparent", position: "item-aligned", disabled, includeClear: false, useChips: false, value: validValue ? internalValue.map(_temp2$a) : [], onValueChange: onChange, children: enumValues?.map((enumConfig) => /* @__PURE__ */ jsx(MultiSelectItem, { value: String(enumConfig.id), children: /* @__PURE__ */ jsx(EnumValuesChip, { enumKey: enumConfig.id, enumValues, size: small ? "small" : "medium" }) }, enumConfig.id)) }) : /* @__PURE__ */ jsx(Select, { inputRef: ref, size: "large", fullWidth: true, className: "w-full h-full p-0 bg-transparent", position: "item-aligned", disabled, padding: false, value: validValue ? internalValue?.toString() : "", onValueChange: onChange, renderValue, children: enumValues?.map((enumConfig_0) => /* @__PURE__ */ jsx(SelectItem, { value: String(enumConfig_0.id), children: /* @__PURE__ */ jsx(EnumValuesChip, { enumKey: enumConfig_0.id, enumValues, size: small ? "small" : "medium" }) }, enumConfig_0.id)) });
7406
7422
  $[10] = disabled;
7407
7423
  $[11] = enumValues;
7408
7424
  $[12] = internalValue;
@@ -7417,10 +7433,10 @@ function VirtualTableSelect(props) {
7417
7433
  }
7418
7434
  return t4;
7419
7435
  }
7420
- function _temp2$b(v_0) {
7436
+ function _temp2$a(v_0) {
7421
7437
  return v_0.toString();
7422
7438
  }
7423
- function _temp$m(v) {
7439
+ function _temp$l(v) {
7424
7440
  return parseFloat(v);
7425
7441
  }
7426
7442
  function VirtualTableNumberInput(props) {
@@ -7979,7 +7995,7 @@ function StorageUpload$1(t0) {
7979
7995
  const snackbarContext = useSnackbarController();
7980
7996
  let t1;
7981
7997
  if ($[0] !== storage.acceptedFiles) {
7982
- t1 = storage.acceptedFiles ? storage.acceptedFiles.map(_temp$l).reduce(_temp2$a, {}) : void 0;
7998
+ t1 = storage.acceptedFiles ? storage.acceptedFiles.map(_temp$k).reduce(_temp2$9, {}) : void 0;
7983
7999
  $[0] = storage.acceptedFiles;
7984
8000
  $[1] = t1;
7985
8001
  } else {
@@ -8202,13 +8218,13 @@ function StorageUpload$1(t0) {
8202
8218
  }
8203
8219
  return t20;
8204
8220
  }
8205
- function _temp2$a(a, b) {
8221
+ function _temp2$9(a, b) {
8206
8222
  return {
8207
8223
  ...a,
8208
8224
  ...b
8209
8225
  };
8210
8226
  }
8211
- function _temp$l(e) {
8227
+ function _temp$k(e) {
8212
8228
  return {
8213
8229
  [e]: []
8214
8230
  };
@@ -8315,7 +8331,7 @@ const TableReferenceFieldInternal = React__default.memo(function TableReferenceF
8315
8331
  let t1;
8316
8332
  if ($[2] !== updateValue) {
8317
8333
  t1 = (entities) => {
8318
- updateValue(entities.map(_temp$k));
8334
+ updateValue(entities.map(_temp$j));
8319
8335
  };
8320
8336
  $[2] = updateValue;
8321
8337
  $[3] = t1;
@@ -8325,7 +8341,7 @@ const TableReferenceFieldInternal = React__default.memo(function TableReferenceF
8325
8341
  const onMultipleEntitiesSelected = t1;
8326
8342
  let t2;
8327
8343
  if ($[4] !== internalValue) {
8328
- t2 = internalValue ? Array.isArray(internalValue) ? internalValue.map(_temp2$9) : internalValue.id ? [internalValue.id] : [] : [];
8344
+ t2 = internalValue ? Array.isArray(internalValue) ? internalValue.map(_temp2$8) : internalValue.id ? [internalValue.id] : [] : [];
8329
8345
  $[4] = internalValue;
8330
8346
  $[5] = t2;
8331
8347
  } else {
@@ -8476,10 +8492,10 @@ const TableReferenceFieldInternal = React__default.memo(function TableReferenceF
8476
8492
  }
8477
8493
  return t10;
8478
8494
  }, equal);
8479
- function _temp$k(e) {
8495
+ function _temp$j(e) {
8480
8496
  return getReferenceFrom(e);
8481
8497
  }
8482
- function _temp2$9(ref) {
8498
+ function _temp2$8(ref) {
8483
8499
  return ref.id;
8484
8500
  }
8485
8501
  yup.addMethod(yup.array, "uniqueInArray", function(mapper = (a) => a, message) {
@@ -9311,7 +9327,14 @@ const PropertyTableCell = React__default.memo(function PropertyTableCell2({
9311
9327
  }
9312
9328
  if (!customField && (!customPreview || selected)) {
9313
9329
  const isAStorageProperty = isStorageProperty(property);
9314
- if (isAStorageProperty) {
9330
+ if (property.dataType === "string" && property.reference?.path) {
9331
+ const stringProperty = property;
9332
+ const path_0 = stringProperty.reference?.path;
9333
+ const referenceProperty = stringProperty.reference;
9334
+ const referenceValue = internalValue ? new EntityReference(internalValue, path_0) : void 0;
9335
+ innerComponent = /* @__PURE__ */ jsx(TableReferenceField, { name: propertyKey, internalValue: referenceValue, updateValue: (v) => updateValue(v ? v.id : null), disabled, size, path: path_0, multiselect: false, previewProperties: referenceProperty.previewProperties, includeId: referenceProperty.includeId, includeEntityLink: referenceProperty.includeEntityLink, title: stringProperty.name, forceFilter: referenceProperty.forceFilter });
9336
+ allowScroll = false;
9337
+ } else if (isAStorageProperty) {
9315
9338
  innerComponent = /* @__PURE__ */ jsx(TableStorageUpload, { error: validationError ?? error, disabled, focused: selected, selected, openPopup: setPopupCell ? openPopup : void 0, property, entity, path, value: internalValue, previewSize: getPreviewSizeFrom(size), updateValue, propertyKey });
9316
9339
  includeActions = false;
9317
9340
  showExpandIcon = true;
@@ -9327,12 +9350,12 @@ const PropertyTableCell = React__default.memo(function PropertyTableCell2({
9327
9350
  allowScroll = true;
9328
9351
  }
9329
9352
  } else if (selected && property.dataType === "string") {
9330
- const stringProperty = property;
9331
- if (stringProperty.enumValues) {
9332
- innerComponent = /* @__PURE__ */ jsx(VirtualTableSelect, { name: propertyKey, multiple: false, focused: selected, disabled, valueType: "string", small: getPreviewSizeFrom(size) !== "medium", enumValues: stringProperty.enumValues, error: validationError ?? error, internalValue, updateValue });
9353
+ const stringProperty_0 = property;
9354
+ if (stringProperty_0.enumValues) {
9355
+ innerComponent = /* @__PURE__ */ jsx(VirtualTableSelect, { name: propertyKey, multiple: false, focused: selected, disabled, valueType: "string", small: getPreviewSizeFrom(size) !== "medium", enumValues: stringProperty_0.enumValues, error: validationError ?? error, internalValue, updateValue });
9333
9356
  fullHeight = true;
9334
- } else if (stringProperty.markdown || !stringProperty.storage) {
9335
- const multiline = Boolean(stringProperty.multiline) || Boolean(stringProperty.markdown);
9357
+ } else if (stringProperty_0.markdown || !stringProperty_0.storage || !stringProperty_0.reference) {
9358
+ const multiline = Boolean(stringProperty_0.multiline) || Boolean(stringProperty_0.markdown);
9336
9359
  innerComponent = /* @__PURE__ */ jsx(VirtualTableInput, { error: validationError ?? error, disabled, multiline, focused: selected, value: internalValue, updateValue });
9337
9360
  allowScroll = true;
9338
9361
  }
@@ -9619,14 +9642,14 @@ function CollectionTableToolbar(t0) {
9619
9642
  }
9620
9643
  let t5;
9621
9644
  if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
9622
- t5 = ["xs", "s", "m", "l", "xl"].map(_temp2$8);
9645
+ t5 = ["xs", "s", "m", "l", "xl"].map(_temp2$7);
9623
9646
  $[5] = t5;
9624
9647
  } else {
9625
9648
  t5 = $[5];
9626
9649
  }
9627
9650
  let t6;
9628
9651
  if ($[6] !== t3 || $[7] !== t4) {
9629
- t6 = /* @__PURE__ */ jsx(Tooltip, { title: "Table row size", side: "right", sideOffset: 4, children: /* @__PURE__ */ jsx(Select, { value: t3, className: "w-16 ml-2", size: "small", onValueChange: t4, renderValue: _temp$j, children: t5 }) });
9652
+ t6 = /* @__PURE__ */ jsx(Tooltip, { title: "Table row size", side: "right", sideOffset: 4, children: /* @__PURE__ */ jsx(Select, { value: t3, className: "w-16 ml-2", size: "small", onValueChange: t4, renderValue: _temp$i, children: t5 }) });
9630
9653
  $[6] = t3;
9631
9654
  $[7] = t4;
9632
9655
  $[8] = t6;
@@ -9710,10 +9733,10 @@ function CollectionTableToolbar(t0) {
9710
9733
  }
9711
9734
  return t13;
9712
9735
  }
9713
- function _temp2$8(size_0) {
9736
+ function _temp2$7(size_0) {
9714
9737
  return /* @__PURE__ */ jsx(SelectItem, { value: size_0, className: "w-12 font-medium text-center", children: size_0.toUpperCase() }, size_0);
9715
9738
  }
9716
- function _temp$j(v_0) {
9739
+ function _temp$i(v_0) {
9717
9740
  return /* @__PURE__ */ jsx("div", { className: "font-medium", children: v_0.toUpperCase() });
9718
9741
  }
9719
9742
  function getTableCellAlignment(property) {
@@ -10833,7 +10856,7 @@ const SafeLinkRenderer = (t0) => {
10833
10856
  let t1;
10834
10857
  if ($[0] !== text) {
10835
10858
  const urlRegex = /https?:\/\/[^\s]+/g;
10836
- t1 = text.replace(urlRegex, _temp$i);
10859
+ t1 = text.replace(urlRegex, _temp$h);
10837
10860
  $[0] = text;
10838
10861
  $[1] = t1;
10839
10862
  } else {
@@ -10852,7 +10875,7 @@ const SafeLinkRenderer = (t0) => {
10852
10875
  }
10853
10876
  return t2;
10854
10877
  };
10855
- function _temp$i(url) {
10878
+ function _temp$h(url) {
10856
10879
  return `<a href="${url}" class="underline" target="_blank">Link</a><br/>`;
10857
10880
  }
10858
10881
  const operationLabels$2 = {
@@ -11052,7 +11075,7 @@ function StringNumberFilterField(t0) {
11052
11075
  }
11053
11076
  let t5;
11054
11077
  if ($[14] !== possibleOperations) {
11055
- t5 = possibleOperations.map(_temp2$7);
11078
+ t5 = possibleOperations.map(_temp2$6);
11056
11079
  $[14] = possibleOperations;
11057
11080
  $[15] = t5;
11058
11081
  } else {
@@ -11060,7 +11083,7 @@ function StringNumberFilterField(t0) {
11060
11083
  }
11061
11084
  let t6;
11062
11085
  if ($[16] !== operation || $[17] !== t4 || $[18] !== t5) {
11063
- t6 = /* @__PURE__ */ jsx("div", { className: "w-[80px]", children: /* @__PURE__ */ jsx(Select, { value: operation, fullWidth: true, position: "item-aligned", onValueChange: t4, renderValue: _temp$h, children: t5 }) });
11086
+ t6 = /* @__PURE__ */ jsx("div", { className: "w-[80px]", children: /* @__PURE__ */ jsx(Select, { value: operation, fullWidth: true, position: "item-aligned", onValueChange: t4, renderValue: _temp$g, children: t5 }) });
11064
11087
  $[16] = operation;
11065
11088
  $[17] = t4;
11066
11089
  $[18] = t5;
@@ -11111,8 +11134,8 @@ function StringNumberFilterField(t0) {
11111
11134
  }
11112
11135
  let t9;
11113
11136
  if ($[34] !== dataType || $[35] !== enumValues || $[36] !== internalValue || $[37] !== multiple || $[38] !== name || $[39] !== operation || $[40] !== updateFilter) {
11114
- t9 = enumValues && multiple && /* @__PURE__ */ jsx(MultiSelect, { position: "item-aligned", value: Array.isArray(internalValue) ? internalValue.map(_temp3$4) : [], onValueChange: (value_2) => {
11115
- updateFilter(operation, dataType === "number" ? value_2.map(_temp4$3) : value_2);
11137
+ t9 = enumValues && multiple && /* @__PURE__ */ jsx(MultiSelect, { position: "item-aligned", value: Array.isArray(internalValue) ? internalValue.map(_temp3$3) : [], onValueChange: (value_2) => {
11138
+ updateFilter(operation, dataType === "number" ? value_2.map(_temp4$2) : value_2);
11116
11139
  }, multiple, endAdornment: internalValue && /* @__PURE__ */ jsx(IconButton, { className: "absolute right-2 top-3", onClick: (e_2) => updateFilter(operation, void 0), children: /* @__PURE__ */ jsx(CloseIcon, {}) }), children: enumValues.map((enumConfig_0) => /* @__PURE__ */ jsx(MultiSelectItem, { value: String(enumConfig_0.id), children: /* @__PURE__ */ jsx(EnumValuesChip, { enumKey: String(enumConfig_0.id), enumValues, size: "small" }) }, `select_value_${name}_${enumConfig_0.id}`)) });
11117
11140
  $[34] = dataType;
11118
11141
  $[35] = enumValues;
@@ -11175,16 +11198,16 @@ function StringNumberFilterField(t0) {
11175
11198
  }
11176
11199
  return t12;
11177
11200
  }
11178
- function _temp4$3(v) {
11201
+ function _temp4$2(v) {
11179
11202
  return parseInt(v);
11180
11203
  }
11181
- function _temp3$4(e_1) {
11204
+ function _temp3$3(e_1) {
11182
11205
  return String(e_1);
11183
11206
  }
11184
- function _temp2$7(op_1) {
11207
+ function _temp2$6(op_1) {
11185
11208
  return /* @__PURE__ */ jsx(SelectItem, { value: op_1, children: operationLabels$1[op_1] }, op_1);
11186
11209
  }
11187
- function _temp$h(op_0) {
11210
+ function _temp$g(op_0) {
11188
11211
  return operationLabels$1[op_0];
11189
11212
  }
11190
11213
  function BooleanFilterField(t0) {
@@ -11315,7 +11338,7 @@ function DateTimeFilterField(t0) {
11315
11338
  }
11316
11339
  let t5;
11317
11340
  if ($[11] !== possibleOperations) {
11318
- t5 = possibleOperations.map(_temp2$6);
11341
+ t5 = possibleOperations.map(_temp2$5);
11319
11342
  $[11] = possibleOperations;
11320
11343
  $[12] = t5;
11321
11344
  } else {
@@ -11323,7 +11346,7 @@ function DateTimeFilterField(t0) {
11323
11346
  }
11324
11347
  let t6;
11325
11348
  if ($[13] !== operation || $[14] !== t4 || $[15] !== t5) {
11326
- t6 = /* @__PURE__ */ jsx("div", { className: "w-[80px]", children: /* @__PURE__ */ jsx(Select, { value: operation, size: "large", fullWidth: true, onValueChange: t4, renderValue: _temp$g, children: t5 }) });
11349
+ t6 = /* @__PURE__ */ jsx("div", { className: "w-[80px]", children: /* @__PURE__ */ jsx(Select, { value: operation, size: "large", fullWidth: true, onValueChange: t4, renderValue: _temp$f, children: t5 }) });
11327
11350
  $[13] = operation;
11328
11351
  $[14] = t4;
11329
11352
  $[15] = t5;
@@ -11409,10 +11432,10 @@ function DateTimeFilterField(t0) {
11409
11432
  }
11410
11433
  return t14;
11411
11434
  }
11412
- function _temp2$6(op_1) {
11435
+ function _temp2$5(op_1) {
11413
11436
  return /* @__PURE__ */ jsx(SelectItem, { value: op_1, children: operationLabels[op_1] }, op_1);
11414
11437
  }
11415
- function _temp$g(op_0) {
11438
+ function _temp$f(op_0) {
11416
11439
  return operationLabels[op_0];
11417
11440
  }
11418
11441
  const SelectableTable = function SelectableTable2({
@@ -12116,7 +12139,7 @@ function useTableSearchHelper(t0) {
12116
12139
  const searchBlocked = t12;
12117
12140
  let t2;
12118
12141
  if ($[15] !== customizationController.plugins || $[16] !== dataSource?.initTextSearch) {
12119
- t2 = Boolean(dataSource?.initTextSearch) || customizationController.plugins?.find(_temp$f);
12142
+ t2 = Boolean(dataSource?.initTextSearch) || customizationController.plugins?.find(_temp$e);
12120
12143
  $[15] = customizationController.plugins;
12121
12144
  $[16] = dataSource?.initTextSearch;
12122
12145
  $[17] = t2;
@@ -12208,7 +12231,7 @@ function useTableSearchHelper(t0) {
12208
12231
  }
12209
12232
  return t1;
12210
12233
  }
12211
- function _temp$f(p_0) {
12234
+ function _temp$e(p_0) {
12212
12235
  return Boolean(p_0.collectionView?.onTextSearchClick);
12213
12236
  }
12214
12237
  function DeleteEntityDialog({
@@ -12678,198 +12701,415 @@ function ReferenceDialogActions(t0) {
12678
12701
  function toArray(input) {
12679
12702
  return Array.isArray(input) ? input : input ? [input] : [];
12680
12703
  }
12681
- function NavigationGroup(t0) {
12682
- const $ = c(14);
12704
+ function NavigationChip(t0) {
12705
+ const $ = c(18);
12683
12706
  const {
12684
- children,
12685
- group
12707
+ entry
12686
12708
  } = t0;
12709
+ const navigate = useNavigate();
12687
12710
  const userConfigurationPersistence = useUserConfigurationPersistence();
12688
- const t1 = !(userConfigurationPersistence?.collapsedGroups ?? []).includes(group ?? "ungrouped");
12711
+ if (!userConfigurationPersistence) {
12712
+ return null;
12713
+ }
12714
+ let t1;
12715
+ if ($[0] !== entry.path || $[1] !== userConfigurationPersistence.favouritePaths) {
12716
+ t1 = userConfigurationPersistence.favouritePaths.includes(entry.path);
12717
+ $[0] = entry.path;
12718
+ $[1] = userConfigurationPersistence.favouritePaths;
12719
+ $[2] = t1;
12720
+ } else {
12721
+ t1 = $[2];
12722
+ }
12723
+ const favourite = t1;
12689
12724
  let t2;
12690
- if ($[0] !== group || $[1] !== userConfigurationPersistence) {
12691
- t2 = (expanded) => {
12692
- if (userConfigurationPersistence) {
12693
- if (!expanded) {
12694
- const paths = (userConfigurationPersistence.collapsedGroups ?? []).concat(group ?? "ungrouped");
12695
- userConfigurationPersistence.setCollapsedGroups(paths);
12696
- } else {
12697
- userConfigurationPersistence.setCollapsedGroups((userConfigurationPersistence.collapsedGroups ?? []).filter((g) => g !== (group ?? "ungrouped")));
12698
- }
12725
+ if ($[3] !== entry.path || $[4] !== favourite || $[5] !== userConfigurationPersistence) {
12726
+ t2 = (e) => {
12727
+ e.preventDefault();
12728
+ e.stopPropagation();
12729
+ if (favourite) {
12730
+ userConfigurationPersistence.setFavouritePaths(userConfigurationPersistence.favouritePaths.filter((p) => p !== entry.path));
12731
+ } else {
12732
+ userConfigurationPersistence.setFavouritePaths([...userConfigurationPersistence.favouritePaths, entry.path]);
12699
12733
  }
12700
12734
  };
12701
- $[0] = group;
12702
- $[1] = userConfigurationPersistence;
12703
- $[2] = t2;
12735
+ $[3] = entry.path;
12736
+ $[4] = favourite;
12737
+ $[5] = userConfigurationPersistence;
12738
+ $[6] = t2;
12704
12739
  } else {
12705
- t2 = $[2];
12740
+ t2 = $[6];
12706
12741
  }
12742
+ const onIconClick = t2;
12707
12743
  let t3;
12708
- if ($[3] !== group) {
12709
- t3 = group?.toUpperCase() ?? "Views".toUpperCase();
12710
- $[3] = group;
12711
- $[4] = t3;
12712
- } else {
12713
- t3 = $[4];
12714
- }
12715
- let t4;
12716
- if ($[5] !== t3) {
12717
- t4 = /* @__PURE__ */ jsx(Typography, { color: "secondary", className: "font-medium ml-1", children: t3 });
12718
- $[5] = t3;
12719
- $[6] = t4;
12744
+ if ($[7] !== entry.url || $[8] !== navigate) {
12745
+ t3 = () => navigate(entry.url);
12746
+ $[7] = entry.url;
12747
+ $[8] = navigate;
12748
+ $[9] = t3;
12720
12749
  } else {
12721
- t4 = $[6];
12750
+ t3 = $[9];
12722
12751
  }
12752
+ const t4 = favourite ? "text-secondary" : "text-surface-400 dark:text-surface-500";
12723
12753
  let t5;
12724
- if ($[7] !== children) {
12725
- t5 = /* @__PURE__ */ jsx("div", { className: "mb-8", children });
12726
- $[7] = children;
12727
- $[8] = t5;
12754
+ if ($[10] !== onIconClick || $[11] !== t4) {
12755
+ t5 = /* @__PURE__ */ jsx(StarIcon, { onClick: onIconClick, size: 18, className: t4 });
12756
+ $[10] = onIconClick;
12757
+ $[11] = t4;
12758
+ $[12] = t5;
12728
12759
  } else {
12729
- t5 = $[8];
12760
+ t5 = $[12];
12730
12761
  }
12731
12762
  let t6;
12732
- if ($[9] !== t1 || $[10] !== t2 || $[11] !== t4 || $[12] !== t5) {
12733
- t6 = /* @__PURE__ */ jsx(ExpandablePanel, { invisible: true, titleClassName: "font-medium text-sm text-surface-600 dark:text-surface-400", innerClassName: "py-4", initiallyExpanded: t1, onExpandedChange: t2, title: t4, children: t5 });
12734
- $[9] = t1;
12735
- $[10] = t2;
12736
- $[11] = t4;
12737
- $[12] = t5;
12738
- $[13] = t6;
12763
+ if ($[13] !== entry.name || $[14] !== entry.path || $[15] !== t3 || $[16] !== t5) {
12764
+ t6 = /* @__PURE__ */ jsx(Chip, { onClick: t3, icon: t5, children: entry.name }, entry.path);
12765
+ $[13] = entry.name;
12766
+ $[14] = entry.path;
12767
+ $[15] = t3;
12768
+ $[16] = t5;
12769
+ $[17] = t6;
12739
12770
  } else {
12740
- t6 = $[13];
12771
+ t6 = $[17];
12741
12772
  }
12742
12773
  return t6;
12743
12774
  }
12744
- function NavigationCard(t0) {
12745
- const $ = c(23);
12746
- const {
12747
- name,
12748
- description,
12749
- icon,
12750
- actions,
12751
- onClick
12752
- } = t0;
12775
+ function FavouritesView(t0) {
12776
+ const $ = c(17);
12777
+ const navigationController = useNavigationController();
12778
+ const userConfigurationPersistence = useUserConfigurationPersistence();
12779
+ if (!userConfigurationPersistence) {
12780
+ return null;
12781
+ }
12753
12782
  let t1;
12754
- if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
12755
- t1 = cls("h-full p-4 cursor-pointer min-h-[230px]");
12756
- $[0] = t1;
12783
+ if ($[0] !== userConfigurationPersistence?.favouritePaths) {
12784
+ t1 = userConfigurationPersistence?.favouritePaths ?? [];
12785
+ $[0] = userConfigurationPersistence?.favouritePaths;
12786
+ $[1] = t1;
12757
12787
  } else {
12758
- t1 = $[0];
12788
+ t1 = $[1];
12759
12789
  }
12790
+ let T0;
12760
12791
  let t2;
12761
- if ($[1] !== onClick) {
12762
- t2 = () => {
12763
- onClick?.();
12764
- };
12765
- $[1] = onClick;
12766
- $[2] = t2;
12767
- } else {
12768
- t2 = $[2];
12769
- }
12770
12792
  let t3;
12771
- if ($[3] !== actions) {
12772
- t3 = /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", onClick: _temp$e, children: actions });
12773
- $[3] = actions;
12774
- $[4] = t3;
12775
- } else {
12776
- t3 = $[4];
12777
- }
12778
12793
  let t4;
12779
- if ($[5] !== icon || $[6] !== t3) {
12780
- t4 = /* @__PURE__ */ jsxs("div", { className: "h-10 flex items-center w-full justify-between text-surface-300 dark:text-surface-600", children: [
12781
- icon,
12782
- t3
12783
- ] });
12784
- $[5] = icon;
12794
+ if ($[2] !== navigationController.topLevelNavigation?.navigationEntries || $[3] !== t1) {
12795
+ let t52;
12796
+ if ($[8] !== navigationController.topLevelNavigation?.navigationEntries) {
12797
+ t52 = (path) => navigationController.topLevelNavigation?.navigationEntries.find((entry) => entry.path === path);
12798
+ $[8] = navigationController.topLevelNavigation?.navigationEntries;
12799
+ $[9] = t52;
12800
+ } else {
12801
+ t52 = $[9];
12802
+ }
12803
+ const favouriteCollections = t1.map(t52).filter(Boolean);
12804
+ T0 = Collapse;
12805
+ t4 = favouriteCollections.length > 0;
12806
+ t2 = "flex flex-row flex-wrap gap-2 pb-2 min-h-[32px]";
12807
+ t3 = favouriteCollections.map(_temp$d);
12808
+ $[2] = navigationController.topLevelNavigation?.navigationEntries;
12809
+ $[3] = t1;
12810
+ $[4] = T0;
12811
+ $[5] = t2;
12785
12812
  $[6] = t3;
12786
12813
  $[7] = t4;
12787
12814
  } else {
12815
+ T0 = $[4];
12816
+ t2 = $[5];
12817
+ t3 = $[6];
12788
12818
  t4 = $[7];
12789
12819
  }
12790
12820
  let t5;
12791
- if ($[8] !== name) {
12792
- t5 = /* @__PURE__ */ jsx(Typography, { gutterBottom: true, variant: "h5", component: "h2", children: name });
12793
- $[8] = name;
12794
- $[9] = t5;
12821
+ if ($[10] !== t2 || $[11] !== t3) {
12822
+ t5 = /* @__PURE__ */ jsx("div", { className: t2, children: t3 });
12823
+ $[10] = t2;
12824
+ $[11] = t3;
12825
+ $[12] = t5;
12795
12826
  } else {
12796
- t5 = $[9];
12827
+ t5 = $[12];
12797
12828
  }
12798
12829
  let t6;
12799
- if ($[10] !== description) {
12800
- t6 = description && /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "secondary", component: "div", children: /* @__PURE__ */ jsx(Markdown, { source: description, size: "small" }) });
12801
- $[10] = description;
12802
- $[11] = t6;
12803
- } else {
12804
- t6 = $[11];
12805
- }
12806
- let t7;
12807
- if ($[12] !== t4 || $[13] !== t5 || $[14] !== t6) {
12808
- t7 = /* @__PURE__ */ jsxs("div", { className: "flex-grow w-full", children: [
12809
- t4,
12810
- t5,
12811
- t6
12812
- ] });
12813
- $[12] = t4;
12814
- $[13] = t5;
12815
- $[14] = t6;
12816
- $[15] = t7;
12817
- } else {
12818
- t7 = $[15];
12819
- }
12820
- let t8;
12821
- if ($[16] === Symbol.for("react.memo_cache_sentinel")) {
12822
- t8 = {
12823
- alignSelf: "flex-end"
12824
- };
12825
- $[16] = t8;
12826
- } else {
12827
- t8 = $[16];
12828
- }
12829
- let t9;
12830
- if ($[17] === Symbol.for("react.memo_cache_sentinel")) {
12831
- t9 = /* @__PURE__ */ jsx("div", { style: t8, children: /* @__PURE__ */ jsx("div", { className: "p-4", children: /* @__PURE__ */ jsx(ArrowForwardIcon, { className: "text-primary" }) }) });
12832
- $[17] = t9;
12833
- } else {
12834
- t9 = $[17];
12835
- }
12836
- let t10;
12837
- if ($[18] !== t7) {
12838
- t10 = /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start h-full", children: [
12839
- t7,
12840
- t9
12841
- ] });
12842
- $[18] = t7;
12843
- $[19] = t10;
12844
- } else {
12845
- t10 = $[19];
12846
- }
12847
- let t11;
12848
- if ($[20] !== t10 || $[21] !== t2) {
12849
- t11 = /* @__PURE__ */ jsx(Card, { className: t1, onClick: t2, children: t10 });
12850
- $[20] = t10;
12851
- $[21] = t2;
12852
- $[22] = t11;
12830
+ if ($[13] !== T0 || $[14] !== t4 || $[15] !== t5) {
12831
+ t6 = /* @__PURE__ */ jsx(T0, { in: t4, children: t5 });
12832
+ $[13] = T0;
12833
+ $[14] = t4;
12834
+ $[15] = t5;
12835
+ $[16] = t6;
12853
12836
  } else {
12854
- t11 = $[22];
12837
+ t6 = $[16];
12855
12838
  }
12856
- return t11;
12839
+ return t6;
12857
12840
  }
12858
- function _temp$e(event) {
12859
- event.preventDefault();
12860
- event.stopPropagation();
12841
+ function _temp$d(entry_0) {
12842
+ return /* @__PURE__ */ jsx(NavigationChip, { entry: entry_0 }, entry_0.path);
12861
12843
  }
12862
- function SmallNavigationCard(t0) {
12863
- const $ = c(10);
12864
- const {
12865
- name,
12866
- url,
12867
- icon
12868
- } = t0;
12869
- let t1;
12870
- if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
12871
- t1 = cls(cardMixin, cardClickableMixin, "cursor-pointer flex flex-row items-center px-4 py-2 text-inherit dark:text-inherit visited:text-inherit visited:dark:text-inherit hover:text-inherit hover:dark:text-inherit ");
12872
- $[0] = t1;
12844
+ const scrollsMap = {};
12845
+ function useRestoreScroll() {
12846
+ const location = useLocation();
12847
+ const containerRef = React__default.useRef(null);
12848
+ const [scroll, setScroll] = React__default.useState(0);
12849
+ const [direction, setDirection] = React__default.useState("down");
12850
+ const handleScroll = useCallback(() => {
12851
+ if (!containerRef.current || !location.key) return;
12852
+ scrollsMap[location.key] = containerRef.current.scrollTop;
12853
+ setScroll(containerRef.current.scrollTop);
12854
+ setDirection(containerRef.current.scrollTop > scroll ? "down" : "up");
12855
+ }, [containerRef, location.key, scroll]);
12856
+ useEffect(() => {
12857
+ const container = containerRef.current;
12858
+ if (!container) return;
12859
+ container.addEventListener("scroll", handleScroll, {
12860
+ passive: true
12861
+ });
12862
+ return () => {
12863
+ if (container) container.removeEventListener("scroll", handleScroll);
12864
+ };
12865
+ }, [containerRef, handleScroll, location]);
12866
+ useEffect(() => {
12867
+ if (!containerRef.current || !scrollsMap[location.key]) return;
12868
+ containerRef.current.scrollTo({
12869
+ top: scrollsMap[location.key],
12870
+ behavior: "auto"
12871
+ });
12872
+ }, [location]);
12873
+ return {
12874
+ containerRef,
12875
+ scroll,
12876
+ direction
12877
+ };
12878
+ }
12879
+ function NavigationGroup(t0) {
12880
+ const $ = c(26);
12881
+ const {
12882
+ children,
12883
+ group,
12884
+ minimised,
12885
+ isPreview,
12886
+ isPotentialCardDropTarget,
12887
+ onEditGroup,
12888
+ dndDisabled
12889
+ } = t0;
12890
+ const [isHovered, setIsHovered] = useState(false);
12891
+ const currentGroupName = group ?? "Views";
12892
+ const t1 = !isPotentialCardDropTarget ? "my-10" : "my-6";
12893
+ let t2;
12894
+ if ($[0] !== t1) {
12895
+ t2 = cls(t1, "transition-all duration-200 ease-in-out");
12896
+ $[0] = t1;
12897
+ $[1] = t2;
12898
+ } else {
12899
+ t2 = $[1];
12900
+ }
12901
+ const t3 = `flex items-center ${isPreview ? "px-1 py-0.5 m-0" : "ml-3.5 mt-6"} `;
12902
+ let t4;
12903
+ let t5;
12904
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
12905
+ t4 = () => setIsHovered(true);
12906
+ t5 = () => setIsHovered(false);
12907
+ $[2] = t4;
12908
+ $[3] = t5;
12909
+ } else {
12910
+ t4 = $[2];
12911
+ t5 = $[3];
12912
+ }
12913
+ const t6 = isPreview ? "body2" : "caption";
12914
+ const t7 = `${isPreview ? "px-1 py-0.5" : "ml-3.5"} font-medium uppercase text-sm text-surface-600 dark:text-surface-400`;
12915
+ let t8;
12916
+ if ($[4] !== currentGroupName || $[5] !== t6 || $[6] !== t7) {
12917
+ t8 = /* @__PURE__ */ jsx(Typography, { variant: t6, component: "h2", color: "secondary", className: t7, children: currentGroupName });
12918
+ $[4] = currentGroupName;
12919
+ $[5] = t6;
12920
+ $[6] = t7;
12921
+ $[7] = t8;
12922
+ } else {
12923
+ t8 = $[7];
12924
+ }
12925
+ let t9;
12926
+ if ($[8] !== currentGroupName || $[9] !== dndDisabled || $[10] !== isHovered || $[11] !== isPreview || $[12] !== onEditGroup) {
12927
+ t9 = !isPreview && onEditGroup && !dndDisabled && /* @__PURE__ */ jsx(IconButton, { size: "smallest", onClick: (e) => {
12928
+ e.stopPropagation();
12929
+ onEditGroup(currentGroupName);
12930
+ }, className: cls("ml-2 ", isHovered ? "opacity-100" : "opacity-0", "transition-opacity duration-100"), children: /* @__PURE__ */ jsx(EditIcon, { size: "smallest" }) });
12931
+ $[8] = currentGroupName;
12932
+ $[9] = dndDisabled;
12933
+ $[10] = isHovered;
12934
+ $[11] = isPreview;
12935
+ $[12] = onEditGroup;
12936
+ $[13] = t9;
12937
+ } else {
12938
+ t9 = $[13];
12939
+ }
12940
+ let t10;
12941
+ if ($[14] !== t3 || $[15] !== t8 || $[16] !== t9) {
12942
+ t10 = /* @__PURE__ */ jsxs("div", { className: t3, onMouseEnter: t4, onMouseLeave: t5, children: [
12943
+ t8,
12944
+ t9
12945
+ ] });
12946
+ $[14] = t3;
12947
+ $[15] = t8;
12948
+ $[16] = t9;
12949
+ $[17] = t10;
12950
+ } else {
12951
+ t10 = $[17];
12952
+ }
12953
+ let t11;
12954
+ if ($[18] !== children || $[19] !== isPreview || $[20] !== minimised) {
12955
+ t11 = isPreview ? children : minimised ? /* @__PURE__ */ jsx("div", { className: cls("mt-4 p-8 bg-surface-accent-200 dark:bg-surface-accent-800 rounded-lg"), style: {
12956
+ minHeight: "50px"
12957
+ } }) : /* @__PURE__ */ jsx("div", { className: cls("mt-4", !minimised ? "pt-0" : ""), children });
12958
+ $[18] = children;
12959
+ $[19] = isPreview;
12960
+ $[20] = minimised;
12961
+ $[21] = t11;
12962
+ } else {
12963
+ t11 = $[21];
12964
+ }
12965
+ let t12;
12966
+ if ($[22] !== t10 || $[23] !== t11 || $[24] !== t2) {
12967
+ t12 = /* @__PURE__ */ jsxs("div", { className: t2, children: [
12968
+ t10,
12969
+ t11
12970
+ ] });
12971
+ $[22] = t10;
12972
+ $[23] = t11;
12973
+ $[24] = t2;
12974
+ $[25] = t12;
12975
+ } else {
12976
+ t12 = $[25];
12977
+ }
12978
+ return t12;
12979
+ }
12980
+ const NavigationCard = React__default.memo(function NavigationCard2(t0) {
12981
+ const $ = c(25);
12982
+ const {
12983
+ name,
12984
+ description,
12985
+ icon,
12986
+ actions,
12987
+ onClick,
12988
+ shrink
12989
+ } = t0;
12990
+ const t1 = shrink && "w-full max-w-full min-h-0 scale-75";
12991
+ let t2;
12992
+ if ($[0] !== t1) {
12993
+ t2 = cls("h-full p-4 cursor-pointer min-h-[230px] transition-all duration-200 ease-in-out", t1);
12994
+ $[0] = t1;
12995
+ $[1] = t2;
12996
+ } else {
12997
+ t2 = $[1];
12998
+ }
12999
+ let t3;
13000
+ if ($[2] !== onClick) {
13001
+ t3 = () => {
13002
+ onClick?.();
13003
+ };
13004
+ $[2] = onClick;
13005
+ $[3] = t3;
13006
+ } else {
13007
+ t3 = $[3];
13008
+ }
13009
+ let t4;
13010
+ if ($[4] !== actions) {
13011
+ t4 = /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", onClick: _temp$c, children: actions });
13012
+ $[4] = actions;
13013
+ $[5] = t4;
13014
+ } else {
13015
+ t4 = $[5];
13016
+ }
13017
+ let t5;
13018
+ if ($[6] !== icon || $[7] !== t4) {
13019
+ t5 = /* @__PURE__ */ jsxs("div", { className: "h-10 flex items-center w-full justify-between text-surface-300 dark:text-surface-600", children: [
13020
+ icon,
13021
+ t4
13022
+ ] });
13023
+ $[6] = icon;
13024
+ $[7] = t4;
13025
+ $[8] = t5;
13026
+ } else {
13027
+ t5 = $[8];
13028
+ }
13029
+ let t6;
13030
+ if ($[9] !== name) {
13031
+ t6 = /* @__PURE__ */ jsx(Typography, { gutterBottom: true, variant: "h5", component: "h2", children: name });
13032
+ $[9] = name;
13033
+ $[10] = t6;
13034
+ } else {
13035
+ t6 = $[10];
13036
+ }
13037
+ let t7;
13038
+ if ($[11] !== description) {
13039
+ t7 = description && /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "secondary", component: "div", children: /* @__PURE__ */ jsx(Markdown, { source: description, size: "small" }) });
13040
+ $[11] = description;
13041
+ $[12] = t7;
13042
+ } else {
13043
+ t7 = $[12];
13044
+ }
13045
+ let t8;
13046
+ if ($[13] !== t5 || $[14] !== t6 || $[15] !== t7) {
13047
+ t8 = /* @__PURE__ */ jsxs("div", { className: "flex-grow w-full", children: [
13048
+ t5,
13049
+ t6,
13050
+ t7
13051
+ ] });
13052
+ $[13] = t5;
13053
+ $[14] = t6;
13054
+ $[15] = t7;
13055
+ $[16] = t8;
13056
+ } else {
13057
+ t8 = $[16];
13058
+ }
13059
+ let t9;
13060
+ if ($[17] === Symbol.for("react.memo_cache_sentinel")) {
13061
+ t9 = {
13062
+ alignSelf: "flex-end"
13063
+ };
13064
+ $[17] = t9;
13065
+ } else {
13066
+ t9 = $[17];
13067
+ }
13068
+ let t10;
13069
+ if ($[18] === Symbol.for("react.memo_cache_sentinel")) {
13070
+ t10 = /* @__PURE__ */ jsx("div", { style: t9, children: /* @__PURE__ */ jsx("div", { className: "p-4", children: /* @__PURE__ */ jsx(ArrowForwardIcon, { className: "text-primary" }) }) });
13071
+ $[18] = t10;
13072
+ } else {
13073
+ t10 = $[18];
13074
+ }
13075
+ let t11;
13076
+ if ($[19] !== t8) {
13077
+ t11 = /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start h-full", children: [
13078
+ t8,
13079
+ t10
13080
+ ] });
13081
+ $[19] = t8;
13082
+ $[20] = t11;
13083
+ } else {
13084
+ t11 = $[20];
13085
+ }
13086
+ let t12;
13087
+ if ($[21] !== t11 || $[22] !== t2 || $[23] !== t3) {
13088
+ t12 = /* @__PURE__ */ jsx(Card, { className: t2, onClick: t3, children: t11 });
13089
+ $[21] = t11;
13090
+ $[22] = t2;
13091
+ $[23] = t3;
13092
+ $[24] = t12;
13093
+ } else {
13094
+ t12 = $[24];
13095
+ }
13096
+ return t12;
13097
+ });
13098
+ function _temp$c(event) {
13099
+ event.preventDefault();
13100
+ event.stopPropagation();
13101
+ }
13102
+ function SmallNavigationCard(t0) {
13103
+ const $ = c(10);
13104
+ const {
13105
+ name,
13106
+ url,
13107
+ icon
13108
+ } = t0;
13109
+ let t1;
13110
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
13111
+ t1 = cls(cardMixin, cardClickableMixin, "cursor-pointer flex flex-row items-center px-4 py-2 text-inherit dark:text-inherit visited:text-inherit visited:dark:text-inherit hover:text-inherit hover:dark:text-inherit ");
13112
+ $[0] = t1;
12873
13113
  } else {
12874
13114
  t1 = $[0];
12875
13115
  }
@@ -12915,7 +13155,7 @@ function SmallNavigationCard(t0) {
12915
13155
  return t5;
12916
13156
  }
12917
13157
  function NavigationCardBinding(t0) {
12918
- const $ = c(34);
13158
+ const $ = c(35);
12919
13159
  const {
12920
13160
  path,
12921
13161
  collection,
@@ -12924,7 +13164,8 @@ function NavigationCardBinding(t0) {
12924
13164
  name,
12925
13165
  description,
12926
13166
  onClick,
12927
- type
13167
+ type,
13168
+ shrink
12928
13169
  } = t0;
12929
13170
  const userConfigurationPersistence = useUserConfigurationPersistence();
12930
13171
  const t1 = collection ?? view;
@@ -13031,533 +13272,1030 @@ function NavigationCardBinding(t0) {
13031
13272
  t6 = $[27];
13032
13273
  }
13033
13274
  let t7;
13034
- if ($[28] !== actions || $[29] !== collectionIcon || $[30] !== description || $[31] !== name || $[32] !== t6) {
13035
- t7 = /* @__PURE__ */ jsx(NavigationCard, { icon: collectionIcon, name, description, actions, onClick: t6 });
13275
+ if ($[28] !== actions || $[29] !== collectionIcon || $[30] !== description || $[31] !== name || $[32] !== shrink || $[33] !== t6) {
13276
+ t7 = /* @__PURE__ */ jsx(NavigationCard, { icon: collectionIcon, name, description, actions, onClick: t6, shrink });
13036
13277
  $[28] = actions;
13037
13278
  $[29] = collectionIcon;
13038
13279
  $[30] = description;
13039
13280
  $[31] = name;
13040
- $[32] = t6;
13041
- $[33] = t7;
13281
+ $[32] = shrink;
13282
+ $[33] = t6;
13283
+ $[34] = t7;
13042
13284
  } else {
13043
- t7 = $[33];
13285
+ t7 = $[34];
13044
13286
  }
13045
13287
  return t7;
13046
13288
  }
13047
- function NavigationChip(t0) {
13048
- const $ = c(18);
13289
+ const animateLayoutChanges = (args) => defaultAnimateLayoutChanges({
13290
+ ...args,
13291
+ wasDragging: true
13292
+ });
13293
+ const dropAnimationConfig = {};
13294
+ const cloneSerializableNavigationEntry = (entry) => {
13295
+ const clonedEntry = {
13296
+ id: entry.id,
13297
+ path: entry.path,
13298
+ url: entry.url,
13299
+ name: entry.name,
13300
+ type: entry.type,
13301
+ collection: entry.collection ? {
13302
+ ...entry.collection
13303
+ } : void 0,
13304
+ view: entry.view ? {
13305
+ ...entry.view
13306
+ } : void 0,
13307
+ ...entry.group && {
13308
+ group: entry.group
13309
+ },
13310
+ ...entry.description && {
13311
+ description: entry.description
13312
+ }
13313
+ };
13314
+ return clonedEntry;
13315
+ };
13316
+ const cloneItemsForDnd = (items) => items.map((g) => ({
13317
+ name: g.name,
13318
+ entries: g.entries.map(cloneSerializableNavigationEntry)
13319
+ }));
13320
+ function SortableNavigationCard(t0) {
13321
+ const $ = c(17);
13049
13322
  const {
13050
- entry
13323
+ entry,
13324
+ onClick
13051
13325
  } = t0;
13052
- const navigate = useNavigate();
13053
- const userConfigurationPersistence = useUserConfigurationPersistence();
13054
- if (!userConfigurationPersistence) {
13055
- return null;
13056
- }
13057
13326
  let t1;
13058
- if ($[0] !== entry.path || $[1] !== userConfigurationPersistence.favouritePaths) {
13059
- t1 = userConfigurationPersistence.favouritePaths.includes(entry.path);
13060
- $[0] = entry.path;
13061
- $[1] = userConfigurationPersistence.favouritePaths;
13062
- $[2] = t1;
13327
+ if ($[0] !== entry.url) {
13328
+ t1 = {
13329
+ id: entry.url,
13330
+ animateLayoutChanges
13331
+ };
13332
+ $[0] = entry.url;
13333
+ $[1] = t1;
13063
13334
  } else {
13064
- t1 = $[2];
13335
+ t1 = $[1];
13065
13336
  }
13066
- const favourite = t1;
13337
+ const {
13338
+ setNodeRef,
13339
+ listeners: listeners2,
13340
+ attributes,
13341
+ transform,
13342
+ transition,
13343
+ isDragging
13344
+ } = useSortable(t1);
13067
13345
  let t2;
13068
- if ($[3] !== entry.path || $[4] !== favourite || $[5] !== userConfigurationPersistence) {
13069
- t2 = (e) => {
13070
- e.preventDefault();
13071
- e.stopPropagation();
13072
- if (favourite) {
13073
- userConfigurationPersistence.setFavouritePaths(userConfigurationPersistence.favouritePaths.filter((p) => p !== entry.path));
13074
- } else {
13075
- userConfigurationPersistence.setFavouritePaths([...userConfigurationPersistence.favouritePaths, entry.path]);
13076
- }
13077
- };
13078
- $[3] = entry.path;
13079
- $[4] = favourite;
13080
- $[5] = userConfigurationPersistence;
13081
- $[6] = t2;
13346
+ let t3;
13347
+ if ($[2] !== transform) {
13348
+ t3 = transform ? CSS.Transform.toString(transform) : void 0;
13349
+ $[2] = transform;
13350
+ $[3] = t3;
13082
13351
  } else {
13083
- t2 = $[6];
13352
+ t3 = $[3];
13084
13353
  }
13085
- const onIconClick = t2;
13086
- let t3;
13087
- if ($[7] !== entry.url || $[8] !== navigate) {
13088
- t3 = () => navigate(entry.url);
13089
- $[7] = entry.url;
13090
- $[8] = navigate;
13091
- $[9] = t3;
13354
+ const t4 = isDragging ? 0 : 1;
13355
+ let t5;
13356
+ if ($[4] !== t3 || $[5] !== t4 || $[6] !== transition) {
13357
+ t5 = {
13358
+ transform: t3,
13359
+ transition,
13360
+ opacity: t4
13361
+ };
13362
+ $[4] = t3;
13363
+ $[5] = t4;
13364
+ $[6] = transition;
13365
+ $[7] = t5;
13092
13366
  } else {
13093
- t3 = $[9];
13367
+ t5 = $[7];
13368
+ }
13369
+ t2 = t5;
13370
+ const style = t2;
13371
+ let t6;
13372
+ if ($[8] !== entry || $[9] !== onClick) {
13373
+ t6 = /* @__PURE__ */ jsx(NavigationCardBinding, { ...entry, onClick });
13374
+ $[8] = entry;
13375
+ $[9] = onClick;
13376
+ $[10] = t6;
13377
+ } else {
13378
+ t6 = $[10];
13379
+ }
13380
+ let t7;
13381
+ if ($[11] !== attributes || $[12] !== listeners2 || $[13] !== setNodeRef || $[14] !== style || $[15] !== t6) {
13382
+ t7 = /* @__PURE__ */ jsx("div", { ref: setNodeRef, style, ...attributes, ...listeners2, children: t6 });
13383
+ $[11] = attributes;
13384
+ $[12] = listeners2;
13385
+ $[13] = setNodeRef;
13386
+ $[14] = style;
13387
+ $[15] = t6;
13388
+ $[16] = t7;
13389
+ } else {
13390
+ t7 = $[16];
13391
+ }
13392
+ return t7;
13393
+ }
13394
+ function NavigationGroupDroppable(t0) {
13395
+ const $ = c(11);
13396
+ const {
13397
+ id,
13398
+ itemIds,
13399
+ children,
13400
+ isPotentialCardDropTarget: t1
13401
+ } = t0;
13402
+ const isPotentialCardDropTarget = t1 === void 0 ? false : t1;
13403
+ let t2;
13404
+ if ($[0] !== id) {
13405
+ t2 = {
13406
+ id
13407
+ };
13408
+ $[0] = id;
13409
+ $[1] = t2;
13410
+ } else {
13411
+ t2 = $[1];
13412
+ }
13413
+ const {
13414
+ setNodeRef
13415
+ } = useDroppable(t2);
13416
+ const t3 = isPotentialCardDropTarget ? "p-2 bg-surface-accent-200 dark:bg-surface-accent-800 rounded-lg" : void 0;
13417
+ let t4;
13418
+ if ($[2] !== t3) {
13419
+ t4 = cls(t3, "transition-all duration-200 ease-in-out");
13420
+ $[2] = t3;
13421
+ $[3] = t4;
13422
+ } else {
13423
+ t4 = $[3];
13094
13424
  }
13095
- const t4 = favourite ? "text-secondary" : "text-surface-400 dark:text-surface-500";
13096
13425
  let t5;
13097
- if ($[10] !== onIconClick || $[11] !== t4) {
13098
- t5 = /* @__PURE__ */ jsx(StarIcon, { onClick: onIconClick, size: 18, className: t4 });
13099
- $[10] = onIconClick;
13100
- $[11] = t4;
13101
- $[12] = t5;
13426
+ if ($[4] !== children || $[5] !== itemIds) {
13427
+ t5 = /* @__PURE__ */ jsx(SortableContext, { items: itemIds, strategy: rectSortingStrategy, children });
13428
+ $[4] = children;
13429
+ $[5] = itemIds;
13430
+ $[6] = t5;
13102
13431
  } else {
13103
- t5 = $[12];
13432
+ t5 = $[6];
13104
13433
  }
13105
13434
  let t6;
13106
- if ($[13] !== entry.name || $[14] !== entry.path || $[15] !== t3 || $[16] !== t5) {
13107
- t6 = /* @__PURE__ */ jsx(Chip, { onClick: t3, icon: t5, children: entry.name }, entry.path);
13108
- $[13] = entry.name;
13109
- $[14] = entry.path;
13110
- $[15] = t3;
13111
- $[16] = t5;
13112
- $[17] = t6;
13435
+ if ($[7] !== setNodeRef || $[8] !== t4 || $[9] !== t5) {
13436
+ t6 = /* @__PURE__ */ jsx("div", { ref: setNodeRef, className: t4, children: t5 });
13437
+ $[7] = setNodeRef;
13438
+ $[8] = t4;
13439
+ $[9] = t5;
13440
+ $[10] = t6;
13113
13441
  } else {
13114
- t6 = $[17];
13442
+ t6 = $[10];
13115
13443
  }
13116
13444
  return t6;
13117
13445
  }
13118
- function FavouritesView(t0) {
13119
- const $ = c(17);
13120
- const navigationController = useNavigationController();
13121
- const userConfigurationPersistence = useUserConfigurationPersistence();
13122
- if (!userConfigurationPersistence) {
13123
- return null;
13124
- }
13446
+ function SortableNavigationGroup(t0) {
13447
+ const $ = c(15);
13448
+ const {
13449
+ groupName,
13450
+ children,
13451
+ disabled
13452
+ } = t0;
13125
13453
  let t1;
13126
- if ($[0] !== userConfigurationPersistence?.favouritePaths) {
13127
- t1 = userConfigurationPersistence?.favouritePaths ?? [];
13128
- $[0] = userConfigurationPersistence?.favouritePaths;
13129
- $[1] = t1;
13454
+ if ($[0] !== disabled || $[1] !== groupName) {
13455
+ t1 = {
13456
+ id: groupName,
13457
+ animateLayoutChanges,
13458
+ disabled
13459
+ };
13460
+ $[0] = disabled;
13461
+ $[1] = groupName;
13462
+ $[2] = t1;
13130
13463
  } else {
13131
- t1 = $[1];
13464
+ t1 = $[2];
13132
13465
  }
13133
- let T0;
13466
+ const {
13467
+ attributes,
13468
+ listeners: listeners2,
13469
+ setNodeRef,
13470
+ transform,
13471
+ transition,
13472
+ isDragging
13473
+ } = useSortable(t1);
13134
13474
  let t2;
13135
13475
  let t3;
13136
- let t4;
13137
- if ($[2] !== navigationController.topLevelNavigation?.navigationEntries || $[3] !== t1) {
13138
- let t52;
13139
- if ($[8] !== navigationController.topLevelNavigation?.navigationEntries) {
13140
- t52 = (path) => navigationController.topLevelNavigation?.navigationEntries.find((entry) => entry.path === path);
13141
- $[8] = navigationController.topLevelNavigation?.navigationEntries;
13142
- $[9] = t52;
13143
- } else {
13144
- t52 = $[9];
13145
- }
13146
- const favouriteCollections = t1.map(t52).filter(Boolean);
13147
- T0 = Collapse;
13148
- t4 = favouriteCollections.length > 0;
13149
- t2 = "flex flex-row flex-wrap gap-2 pb-2 min-h-[32px]";
13150
- t3 = favouriteCollections.map(_temp$d);
13151
- $[2] = navigationController.topLevelNavigation?.navigationEntries;
13152
- $[3] = t1;
13153
- $[4] = T0;
13154
- $[5] = t2;
13155
- $[6] = t3;
13156
- $[7] = t4;
13476
+ if ($[3] !== transform) {
13477
+ t3 = transform ? CSS.Transform.toString(transform) : void 0;
13478
+ $[3] = transform;
13479
+ $[4] = t3;
13157
13480
  } else {
13158
- T0 = $[4];
13159
- t2 = $[5];
13160
- t3 = $[6];
13161
- t4 = $[7];
13481
+ t3 = $[4];
13162
13482
  }
13483
+ const t4 = isDragging ? 0 : 1;
13163
13484
  let t5;
13164
- if ($[10] !== t2 || $[11] !== t3) {
13165
- t5 = /* @__PURE__ */ jsx("div", { className: t2, children: t3 });
13166
- $[10] = t2;
13167
- $[11] = t3;
13168
- $[12] = t5;
13485
+ if ($[5] !== t3 || $[6] !== t4 || $[7] !== transition) {
13486
+ t5 = {
13487
+ transform: t3,
13488
+ transition,
13489
+ opacity: t4
13490
+ };
13491
+ $[5] = t3;
13492
+ $[6] = t4;
13493
+ $[7] = transition;
13494
+ $[8] = t5;
13169
13495
  } else {
13170
- t5 = $[12];
13496
+ t5 = $[8];
13171
13497
  }
13498
+ t2 = t5;
13499
+ const style = t2;
13172
13500
  let t6;
13173
- if ($[13] !== T0 || $[14] !== t4 || $[15] !== t5) {
13174
- t6 = /* @__PURE__ */ jsx(T0, { in: t4, children: t5 });
13175
- $[13] = T0;
13176
- $[14] = t4;
13177
- $[15] = t5;
13178
- $[16] = t6;
13501
+ if ($[9] !== attributes || $[10] !== children || $[11] !== listeners2 || $[12] !== setNodeRef || $[13] !== style) {
13502
+ t6 = /* @__PURE__ */ jsx("div", { ref: setNodeRef, style, ...attributes, ...listeners2, children });
13503
+ $[9] = attributes;
13504
+ $[10] = children;
13505
+ $[11] = listeners2;
13506
+ $[12] = setNodeRef;
13507
+ $[13] = style;
13508
+ $[14] = t6;
13179
13509
  } else {
13180
- t6 = $[16];
13510
+ t6 = $[14];
13181
13511
  }
13182
13512
  return t6;
13183
13513
  }
13184
- function _temp$d(entry_0) {
13185
- return /* @__PURE__ */ jsx(NavigationChip, { entry: entry_0 }, entry_0.path);
13186
- }
13187
- const scrollsMap = {};
13188
- function useRestoreScroll() {
13189
- const location = useLocation();
13190
- const containerRef = React__default.useRef(null);
13191
- const [scroll, setScroll] = React__default.useState(0);
13192
- const [direction, setDirection] = React__default.useState("down");
13193
- const handleScroll = useCallback(() => {
13194
- if (!containerRef.current || !location.key) return;
13195
- scrollsMap[location.key] = containerRef.current.scrollTop;
13196
- setScroll(containerRef.current.scrollTop);
13197
- setDirection(containerRef.current.scrollTop > scroll ? "down" : "up");
13198
- }, [containerRef, location.key, scroll]);
13199
- useEffect(() => {
13200
- const container = containerRef.current;
13201
- if (!container) return;
13202
- container.addEventListener("scroll", handleScroll, {
13203
- passive: true
13204
- });
13205
- return () => {
13206
- if (container) container.removeEventListener("scroll", handleScroll);
13207
- };
13208
- }, [containerRef, handleScroll, location]);
13514
+ function useHomePageDnd({
13515
+ items: dndItems,
13516
+ setItems: setDndItems,
13517
+ disabled,
13518
+ onCardMovedBetweenGroups,
13519
+ onGroupMoved,
13520
+ onNewGroupDrop,
13521
+ onPersist
13522
+ }) {
13523
+ const [activeId, setActiveId] = useState(null);
13524
+ const [activeIsGroup, setActiveIsGroup] = useState(false);
13525
+ const [currentDraggingGroupId, setCurrentDraggingGroupId] = useState(null);
13526
+ const [dndKitActiveNode, setDndKitActiveNode] = useState(null);
13527
+ const [isDraggingCardOnly, setIsDraggingCardOnly] = useState(false);
13528
+ const [dialogOpenForGroup, setDialogOpenForGroup] = useState(null);
13529
+ const [isHoveringNewGroupDropZone, setIsHoveringNewGroupDropZone] = useState(false);
13530
+ const interimItemsRef = useRef(null);
13209
13531
  useEffect(() => {
13210
- if (!containerRef.current || !scrollsMap[location.key]) return;
13211
- containerRef.current.scrollTo({
13212
- top: scrollsMap[location.key],
13213
- behavior: "auto"
13532
+ interimItemsRef.current = dndItems;
13533
+ }, [dndItems]);
13534
+ const mouseSensor = useSensor(MouseSensor, {
13535
+ activationConstraint: {
13536
+ distance: 10
13537
+ }
13538
+ });
13539
+ const touchSensor = useSensor(TouchSensor, {
13540
+ activationConstraint: {
13541
+ delay: 150,
13542
+ tolerance: 5
13543
+ }
13544
+ });
13545
+ const keyboardSensor = useSensor(KeyboardSensor);
13546
+ const sensors = useSensors(...disabled ? [] : [mouseSensor, touchSensor, keyboardSensor]);
13547
+ const dndContainers = useMemo(() => dndItems.map((g) => g.name), [dndItems]);
13548
+ const findDndContainer = useCallback((id) => {
13549
+ if (!id) return void 0;
13550
+ const group = dndItems.find((g_0) => g_0.name === id);
13551
+ if (group) return group.name;
13552
+ for (const g_1 of dndItems) {
13553
+ if (g_1.entries.some((e) => e.url === id)) return g_1.name;
13554
+ }
13555
+ return void 0;
13556
+ }, [dndItems]);
13557
+ const lastOverId = useRef(null);
13558
+ const recentlyMovedToNewContainer = useRef(false);
13559
+ const collisionDetection = useCallback((args) => {
13560
+ if (disabled || !activeId) return [];
13561
+ if (activeIsGroup) {
13562
+ const groups = args.droppableContainers.filter((c2) => dndItems.some((g_2) => g_2.name === c2.id));
13563
+ if (!groups.length) return [];
13564
+ return closestCenter({
13565
+ ...args,
13566
+ droppableContainers: groups
13567
+ });
13568
+ }
13569
+ const pointer = pointerWithin(args);
13570
+ if (pointer.length) {
13571
+ const zone = pointer.find((c_0) => c_0.id === "new-group-drop-zone");
13572
+ if (zone) return [zone];
13573
+ const container = pointer.find((c_1) => dndItems.some((g_3) => g_3.name === c_1.id));
13574
+ if (container) {
13575
+ const itemsIn = dndItems.find((g_4) => g_4.name === container.id)?.entries;
13576
+ if (itemsIn?.length) {
13577
+ const closest = closestCorners({
13578
+ ...args,
13579
+ droppableContainers: args.droppableContainers.filter((c_2) => itemsIn.some((e_0) => e_0.url === c_2.id))
13580
+ });
13581
+ if (closest.length) return closest;
13582
+ }
13583
+ return [container];
13584
+ }
13585
+ const first = getFirstCollision(pointer, "id");
13586
+ if (first) return [{
13587
+ id: first
13588
+ }];
13589
+ }
13590
+ const rects = rectIntersection(args);
13591
+ const zoneRect = rects.find((c_3) => c_3.id === "new-group-drop-zone");
13592
+ if (zoneRect) return [zoneRect];
13593
+ let overId = getFirstCollision(rects, "id");
13594
+ if (overId != null) {
13595
+ const overIsContainer = dndItems.some((g_5) => g_5.name === overId);
13596
+ if (overIsContainer) {
13597
+ const itemsIn_0 = dndItems.find((g_6) => g_6.name === overId)?.entries;
13598
+ if (itemsIn_0?.length) {
13599
+ const closestItem = closestCorners({
13600
+ ...args,
13601
+ droppableContainers: args.droppableContainers.filter((c_4) => itemsIn_0.some((e_1) => e_1.url === c_4.id))
13602
+ })[0]?.id;
13603
+ if (closestItem) overId = closestItem;
13604
+ }
13605
+ }
13606
+ lastOverId.current = overId;
13607
+ return [{
13608
+ id: overId
13609
+ }];
13610
+ }
13611
+ if (recentlyMovedToNewContainer.current && lastOverId.current && !activeIsGroup) return [{
13612
+ id: lastOverId.current
13613
+ }];
13614
+ return [];
13615
+ }, [activeId, dndItems, disabled, activeIsGroup]);
13616
+ const handleDragStart = ({
13617
+ active
13618
+ }) => {
13619
+ setDndKitActiveNode(active);
13620
+ if (disabled) return;
13621
+ const isGroup = dndItems.some((g_7) => g_7.name === active.id);
13622
+ if (!active.data.current) active.data.current = {};
13623
+ active.data.current.type = isGroup ? "group" : "item";
13624
+ setActiveId(active.id);
13625
+ setActiveIsGroup(isGroup);
13626
+ setIsDraggingCardOnly(!isGroup);
13627
+ if (isGroup) setCurrentDraggingGroupId(active.id);
13628
+ recentlyMovedToNewContainer.current = false;
13629
+ };
13630
+ const handleDragOver = ({
13631
+ active: active_0,
13632
+ over
13633
+ }) => {
13634
+ if (disabled || !over) return;
13635
+ const activeIdNow = active_0.id;
13636
+ const overIdNow = over.id;
13637
+ if (activeIdNow === overIdNow) return;
13638
+ if (activeIsGroup) return;
13639
+ const activeCont = findDndContainer(activeIdNow);
13640
+ const overCont = findDndContainer(overIdNow);
13641
+ if (!activeCont) return;
13642
+ if (overCont && activeCont !== overCont) {
13643
+ recentlyMovedToNewContainer.current = true;
13644
+ const newState = cloneItemsForDnd(dndItems);
13645
+ const srcIdx = newState.findIndex((g_8) => g_8.name === activeCont);
13646
+ const tgtIdx = newState.findIndex((g_9) => g_9.name === overCont);
13647
+ if (srcIdx === -1 || tgtIdx === -1) return;
13648
+ const src = newState[srcIdx];
13649
+ const tgt = newState[tgtIdx];
13650
+ const idxInSrc = src.entries.findIndex((e_2) => e_2.url === activeIdNow);
13651
+ if (idxInSrc === -1) return;
13652
+ const [moved] = src.entries.splice(idxInSrc, 1);
13653
+ tgt.entries.push(moved);
13654
+ interimItemsRef.current = newState;
13655
+ setDndItems(newState);
13656
+ } else if (activeCont === overCont) {
13657
+ recentlyMovedToNewContainer.current = false;
13658
+ }
13659
+ };
13660
+ const handleDragEnd = ({
13661
+ active: active_1,
13662
+ over: over_0
13663
+ }) => {
13664
+ if (disabled || !over_0) {
13665
+ resetDragState();
13666
+ return;
13667
+ }
13668
+ const activeIdNow_0 = active_1.id;
13669
+ const overIdNow_0 = over_0.id;
13670
+ if (activeIsGroup) {
13671
+ if (activeIdNow_0 !== overIdNow_0 && dndItems.some((g_12) => g_12.name === overIdNow_0)) {
13672
+ const from = dndItems.findIndex((g_10) => g_10.name === activeIdNow_0);
13673
+ const to = dndItems.findIndex((g_11) => g_11.name === overIdNow_0);
13674
+ if (from !== -1 && to !== -1) {
13675
+ const newState_0 = arrayMove$1(dndItems, from, to);
13676
+ setDndItems(newState_0);
13677
+ onPersist?.(newState_0);
13678
+ onGroupMoved?.(activeIdNow_0, from, to);
13679
+ }
13680
+ }
13681
+ } else {
13682
+ const activeCont_0 = findDndContainer(activeIdNow_0);
13683
+ if (overIdNow_0 === "new-group-drop-zone") {
13684
+ if (activeCont_0) {
13685
+ const newState_1 = cloneItemsForDnd(dndItems);
13686
+ const srcIdx_0 = newState_1.findIndex((g_13) => g_13.name === activeCont_0);
13687
+ if (srcIdx_0 !== -1) {
13688
+ const src_0 = newState_1[srcIdx_0];
13689
+ const idxInSrc_0 = src_0.entries.findIndex((e_3) => e_3.url === activeIdNow_0);
13690
+ if (idxInSrc_0 !== -1) {
13691
+ const [dragged] = src_0.entries.splice(idxInSrc_0, 1);
13692
+ if (src_0.entries.length === 0) newState_1.splice(srcIdx_0, 1);
13693
+ let tentative = "New Group";
13694
+ let counter = 1;
13695
+ while (newState_1.some((g_14) => g_14.name === tentative)) tentative = `New Group ${counter++}`;
13696
+ newState_1.push({
13697
+ name: tentative,
13698
+ entries: [dragged]
13699
+ });
13700
+ setDndItems(newState_1);
13701
+ onPersist?.(newState_1);
13702
+ setDialogOpenForGroup(tentative);
13703
+ onNewGroupDrop?.();
13704
+ }
13705
+ }
13706
+ }
13707
+ } else {
13708
+ const overCont_0 = findDndContainer(overIdNow_0);
13709
+ if (activeCont_0 === overCont_0) {
13710
+ const grpIdx = dndItems.findIndex((g_15) => g_15.name === activeCont_0);
13711
+ if (grpIdx !== -1) {
13712
+ const group_0 = dndItems[grpIdx];
13713
+ const oldIdx = group_0.entries.findIndex((e_4) => e_4.url === activeIdNow_0);
13714
+ let newIdx = group_0.entries.findIndex((e_5) => e_5.url === overIdNow_0);
13715
+ if (newIdx === -1 && overIdNow_0 === activeCont_0) newIdx = group_0.entries.length - 1;
13716
+ if (oldIdx !== -1 && newIdx !== -1 && oldIdx !== newIdx) {
13717
+ const reordered = arrayMove$1(group_0.entries, oldIdx, newIdx);
13718
+ const newState_2 = [...dndItems];
13719
+ newState_2[grpIdx] = {
13720
+ ...group_0,
13721
+ entries: reordered
13722
+ };
13723
+ setDndItems(newState_2);
13724
+ onPersist?.(newState_2);
13725
+ }
13726
+ }
13727
+ } else if (recentlyMovedToNewContainer.current && interimItemsRef.current) {
13728
+ onPersist?.(interimItemsRef.current);
13729
+ }
13730
+ onCardMovedBetweenGroups?.(dndItems.flatMap((g_16) => g_16.entries).find((e_6) => e_6.url === activeIdNow_0));
13731
+ }
13732
+ }
13733
+ resetDragState();
13734
+ };
13735
+ const resetDragState = () => {
13736
+ setDndKitActiveNode(null);
13737
+ setActiveId(null);
13738
+ setActiveIsGroup(false);
13739
+ setCurrentDraggingGroupId(null);
13740
+ setIsDraggingCardOnly(false);
13741
+ recentlyMovedToNewContainer.current = false;
13742
+ };
13743
+ const handleDragCancel = () => resetDragState();
13744
+ const handleRenameGroup = (oldName, newName) => {
13745
+ setDndItems((current) => {
13746
+ const idx = current.findIndex((g_17) => g_17.name === oldName);
13747
+ if (idx === -1) return current;
13748
+ if (current.some((g_18) => g_18.name === newName && g_18.name !== oldName)) return current;
13749
+ const updated = [...current];
13750
+ updated[idx] = {
13751
+ ...updated[idx],
13752
+ name: newName
13753
+ };
13754
+ onPersist?.(updated);
13755
+ return updated;
13214
13756
  });
13215
- }, [location]);
13757
+ };
13758
+ const activeItemForOverlay = useMemo(() => {
13759
+ if (disabled || !activeId || activeIsGroup) return null;
13760
+ return dndItems.flatMap((g_19) => g_19.entries).find((e_7) => e_7.url === activeId) || null;
13761
+ }, [activeId, dndItems, disabled, activeIsGroup]);
13762
+ const activeGroupData = useMemo(() => {
13763
+ if (disabled || !activeId || !activeIsGroup) return null;
13764
+ return dndItems.find((g_20) => g_20.name === activeId) || null;
13765
+ }, [activeId, dndItems, disabled, activeIsGroup]);
13216
13766
  return {
13217
- containerRef,
13218
- scroll,
13219
- direction
13767
+ sensors,
13768
+ collisionDetection,
13769
+ onDragStart: handleDragStart,
13770
+ onDragOver: handleDragOver,
13771
+ onDragEnd: handleDragEnd,
13772
+ onDragCancel: handleDragCancel,
13773
+ dropAnimation: dropAnimationConfig,
13774
+ activeItemForOverlay,
13775
+ activeGroupData,
13776
+ draggingGroupId: currentDraggingGroupId,
13777
+ containers: dndContainers,
13778
+ dndKitActiveNode,
13779
+ isDraggingCardOnly,
13780
+ dialogOpenForGroup,
13781
+ setDialogOpenForGroup,
13782
+ handleRenameGroup,
13783
+ isHoveringNewGroupDropZone,
13784
+ setIsHoveringNewGroupDropZone
13220
13785
  };
13221
13786
  }
13222
- function DefaultHomePage(t0) {
13223
- const $ = c(71);
13787
+ function NewGroupDropZone(t0) {
13788
+ const $ = c(15);
13224
13789
  const {
13225
- additionalActions,
13226
- additionalChildrenStart,
13227
- additionalChildrenEnd
13790
+ disabled,
13791
+ setIsHovering
13228
13792
  } = t0;
13229
- const context = useFireCMSContext();
13230
- const customizationController = useCustomizationController();
13231
- const navigationController = useNavigationController();
13232
- const fuse = useRef(null);
13233
- if (!navigationController.topLevelNavigation) {
13234
- throw Error("Navigation not ready in FireCMSHomePage");
13793
+ let t1;
13794
+ if ($[0] !== disabled) {
13795
+ t1 = {
13796
+ id: "new-group-drop-zone",
13797
+ disabled
13798
+ };
13799
+ $[0] = disabled;
13800
+ $[1] = t1;
13801
+ } else {
13802
+ t1 = $[1];
13235
13803
  }
13236
13804
  const {
13237
- containerRef,
13238
- direction
13239
- } = useRestoreScroll();
13805
+ setNodeRef,
13806
+ isOver
13807
+ } = useDroppable(t1);
13808
+ const [isVisible, setIsVisible] = useState(false);
13809
+ let t2;
13810
+ if ($[2] !== disabled) {
13811
+ t2 = {
13812
+ onDragStart(t32) {
13813
+ const {
13814
+ active
13815
+ } = t32;
13816
+ if (disabled) {
13817
+ return;
13818
+ }
13819
+ const tp = active.data.current?.type;
13820
+ setIsVisible(tp === "item");
13821
+ },
13822
+ onDragEnd() {
13823
+ setIsVisible(false);
13824
+ },
13825
+ onDragCancel() {
13826
+ setIsVisible(false);
13827
+ }
13828
+ };
13829
+ $[2] = disabled;
13830
+ $[3] = t2;
13831
+ } else {
13832
+ t2 = $[3];
13833
+ }
13834
+ useDndMonitor(t2);
13835
+ let t3;
13836
+ let t4;
13837
+ if ($[4] !== isOver || $[5] !== isVisible || $[6] !== setIsHovering) {
13838
+ t3 = () => {
13839
+ setIsHovering(isOver && isVisible);
13840
+ };
13841
+ t4 = [isOver, isVisible, setIsHovering];
13842
+ $[4] = isOver;
13843
+ $[5] = isVisible;
13844
+ $[6] = setIsHovering;
13845
+ $[7] = t3;
13846
+ $[8] = t4;
13847
+ } else {
13848
+ t3 = $[7];
13849
+ t4 = $[8];
13850
+ }
13851
+ useEffect(t3, t4);
13852
+ if (!isVisible || disabled) {
13853
+ return null;
13854
+ }
13855
+ const t5 = isOver ? "bg-surface-accent-100 dark:bg-surface-accent-800 border-surface-300 dark:border-surface-600" : "bg-surface-50 dark:bg-surface-900 border-surface-200 dark:border-surface-700";
13856
+ let t6;
13857
+ if ($[9] !== t5) {
13858
+ t6 = cls("fixed right-8 top-1/2 -translate-y-1/2 w-[200px] h-[120px] border border-dashed rounded-lg flex items-center justify-center transition-all", t5);
13859
+ $[9] = t5;
13860
+ $[10] = t6;
13861
+ } else {
13862
+ t6 = $[10];
13863
+ }
13864
+ let t7;
13865
+ if ($[11] === Symbol.for("react.memo_cache_sentinel")) {
13866
+ t7 = /* @__PURE__ */ jsx("div", { className: "text-center p-4", children: /* @__PURE__ */ jsx("span", { className: "block font-medium text-sm", children: "Drop here to create a new group" }) });
13867
+ $[11] = t7;
13868
+ } else {
13869
+ t7 = $[11];
13870
+ }
13871
+ let t8;
13872
+ if ($[12] !== setNodeRef || $[13] !== t6) {
13873
+ t8 = /* @__PURE__ */ jsx("div", { ref: setNodeRef, className: t6, children: t7 });
13874
+ $[12] = setNodeRef;
13875
+ $[13] = t6;
13876
+ $[14] = t8;
13877
+ } else {
13878
+ t8 = $[14];
13879
+ }
13880
+ return t8;
13881
+ }
13882
+ function RenameGroupDialog(t0) {
13883
+ const $ = c(41);
13240
13884
  const {
13241
- navigationEntries,
13242
- groups
13243
- } = navigationController.topLevelNavigation;
13244
- const [filteredUrls, setFilteredUrls] = useState(null);
13245
- const performingSearch = Boolean(filteredUrls);
13885
+ open,
13886
+ initialName,
13887
+ existingGroupNames,
13888
+ onClose,
13889
+ onRename
13890
+ } = t0;
13891
+ const [name, setName] = useState(initialName);
13892
+ const [error, setError] = useState(null);
13893
+ const inputRef = useRef(null);
13246
13894
  let t1;
13247
- if ($[0] !== filteredUrls || $[1] !== navigationEntries) {
13248
- t1 = filteredUrls ? filteredUrls.map((url) => navigationEntries.find((e) => e.url === url)).filter(Boolean) : navigationEntries;
13249
- $[0] = filteredUrls;
13250
- $[1] = navigationEntries;
13895
+ let t2;
13896
+ if ($[0] !== initialName || $[1] !== open) {
13897
+ t1 = () => {
13898
+ if (open) {
13899
+ setName(initialName);
13900
+ setError(null);
13901
+ setTimeout(() => {
13902
+ if (inputRef.current) {
13903
+ inputRef.current.focus();
13904
+ inputRef.current.select();
13905
+ }
13906
+ }, 100);
13907
+ }
13908
+ };
13909
+ t2 = [initialName, open];
13910
+ $[0] = initialName;
13911
+ $[1] = open;
13251
13912
  $[2] = t1;
13913
+ $[3] = t2;
13252
13914
  } else {
13253
13915
  t1 = $[2];
13916
+ t2 = $[3];
13254
13917
  }
13255
- const filteredNavigationEntries = t1;
13256
- let t2;
13918
+ useEffect(t1, t2);
13257
13919
  let t3;
13258
- if ($[3] !== navigationEntries) {
13259
- t2 = () => {
13260
- fuse.current = new Fuse(navigationEntries, {
13261
- keys: ["name", "description", "group", "path"]
13262
- });
13920
+ if ($[4] !== existingGroupNames) {
13921
+ t3 = (event) => {
13922
+ const newName = event.target.value;
13923
+ setName(newName);
13924
+ if (!newName.trim()) {
13925
+ setError("Group name cannot be empty.");
13926
+ } else {
13927
+ if (existingGroupNames.includes(newName.trim())) {
13928
+ setError("This group name already exists.");
13929
+ } else {
13930
+ setError(null);
13931
+ }
13932
+ }
13263
13933
  };
13264
- t3 = [navigationEntries];
13265
- $[3] = navigationEntries;
13266
- $[4] = t2;
13934
+ $[4] = existingGroupNames;
13267
13935
  $[5] = t3;
13268
13936
  } else {
13269
- t2 = $[4];
13270
13937
  t3 = $[5];
13271
13938
  }
13272
- useEffect(t2, t3);
13939
+ const handleNameChange = t3;
13273
13940
  let t4;
13274
- if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
13275
- t4 = (value) => {
13276
- if (!value || value === "") {
13277
- setFilteredUrls(null);
13278
- } else {
13279
- const searchResult = fuse.current?.search(value);
13280
- if (searchResult) {
13281
- setFilteredUrls(searchResult.map(_temp$c));
13941
+ if ($[6] !== error || $[7] !== existingGroupNames || $[8] !== name || $[9] !== onClose || $[10] !== onRename) {
13942
+ t4 = () => {
13943
+ const trimmedName = name.trim();
13944
+ if (!trimmedName) {
13945
+ setError("Group name cannot be empty.");
13946
+ return;
13947
+ }
13948
+ if (existingGroupNames.includes(trimmedName)) {
13949
+ setError("This group name already exists.");
13950
+ return;
13951
+ }
13952
+ if (!error) {
13953
+ onRename(trimmedName);
13954
+ onClose();
13955
+ }
13956
+ };
13957
+ $[6] = error;
13958
+ $[7] = existingGroupNames;
13959
+ $[8] = name;
13960
+ $[9] = onClose;
13961
+ $[10] = onRename;
13962
+ $[11] = t4;
13963
+ } else {
13964
+ t4 = $[11];
13965
+ }
13966
+ const handleSave = t4;
13967
+ let t5;
13968
+ if ($[12] !== existingGroupNames || $[13] !== handleSave || $[14] !== name) {
13969
+ t5 = (event_0) => {
13970
+ if (event_0.key === "Enter") {
13971
+ event_0.preventDefault();
13972
+ const trimmedName_0 = name.trim();
13973
+ let currentError = null;
13974
+ if (!trimmedName_0) {
13975
+ currentError = "Group name cannot be empty.";
13976
+ } else {
13977
+ if (existingGroupNames.includes(trimmedName_0)) {
13978
+ currentError = "This group name already exists.";
13979
+ }
13980
+ }
13981
+ if (!currentError && trimmedName_0) {
13982
+ handleSave();
13983
+ } else {
13984
+ if (currentError) {
13985
+ setError(currentError);
13986
+ }
13282
13987
  }
13283
13988
  }
13284
13989
  };
13285
- $[6] = t4;
13990
+ $[12] = existingGroupNames;
13991
+ $[13] = handleSave;
13992
+ $[14] = name;
13993
+ $[15] = t5;
13994
+ } else {
13995
+ t5 = $[15];
13996
+ }
13997
+ const handleKeyDown = t5;
13998
+ if (!open) {
13999
+ return null;
14000
+ }
14001
+ let t6;
14002
+ if ($[16] === Symbol.for("react.memo_cache_sentinel")) {
14003
+ t6 = /* @__PURE__ */ jsx(DialogTitle, { children: "Rename Group" });
14004
+ $[16] = t6;
14005
+ } else {
14006
+ t6 = $[16];
14007
+ }
14008
+ const t7 = !!error;
14009
+ const t8 = error ? "group-name-error" : void 0;
14010
+ let t9;
14011
+ if ($[17] !== handleKeyDown || $[18] !== handleNameChange || $[19] !== name || $[20] !== t7 || $[21] !== t8) {
14012
+ t9 = /* @__PURE__ */ jsx(TextField, { inputRef, label: "Group Name", value: name, onChange: handleNameChange, onKeyDown: handleKeyDown, error: t7, "aria-describedby": t8 });
14013
+ $[17] = handleKeyDown;
14014
+ $[18] = handleNameChange;
14015
+ $[19] = name;
14016
+ $[20] = t7;
14017
+ $[21] = t8;
14018
+ $[22] = t9;
14019
+ } else {
14020
+ t9 = $[22];
14021
+ }
14022
+ let t10;
14023
+ if ($[23] !== error) {
14024
+ t10 = error && /* @__PURE__ */ jsx("p", { id: "group-name-error", style: {
14025
+ display: "none"
14026
+ }, children: error });
14027
+ $[23] = error;
14028
+ $[24] = t10;
14029
+ } else {
14030
+ t10 = $[24];
14031
+ }
14032
+ let t11;
14033
+ if ($[25] !== t10 || $[26] !== t9) {
14034
+ t11 = /* @__PURE__ */ jsxs(DialogContent, { children: [
14035
+ t9,
14036
+ t10
14037
+ ] });
14038
+ $[25] = t10;
14039
+ $[26] = t9;
14040
+ $[27] = t11;
14041
+ } else {
14042
+ t11 = $[27];
14043
+ }
14044
+ let t12;
14045
+ if ($[28] !== onClose) {
14046
+ t12 = /* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "text", children: "Cancel" });
14047
+ $[28] = onClose;
14048
+ $[29] = t12;
14049
+ } else {
14050
+ t12 = $[29];
14051
+ }
14052
+ const t13 = !!error || !name.trim();
14053
+ let t14;
14054
+ if ($[30] !== handleSave || $[31] !== t13) {
14055
+ t14 = /* @__PURE__ */ jsx(Button, { onClick: handleSave, disabled: t13, children: "Save" });
14056
+ $[30] = handleSave;
14057
+ $[31] = t13;
14058
+ $[32] = t14;
14059
+ } else {
14060
+ t14 = $[32];
14061
+ }
14062
+ let t15;
14063
+ if ($[33] !== t12 || $[34] !== t14) {
14064
+ t15 = /* @__PURE__ */ jsxs(DialogActions, { children: [
14065
+ t12,
14066
+ t14
14067
+ ] });
14068
+ $[33] = t12;
14069
+ $[34] = t14;
14070
+ $[35] = t15;
14071
+ } else {
14072
+ t15 = $[35];
14073
+ }
14074
+ let t16;
14075
+ if ($[36] !== onClose || $[37] !== open || $[38] !== t11 || $[39] !== t15) {
14076
+ t16 = /* @__PURE__ */ jsxs(Dialog, { open, onOpenChange: onClose, children: [
14077
+ t6,
14078
+ t11,
14079
+ t15
14080
+ ] });
14081
+ $[36] = onClose;
14082
+ $[37] = open;
14083
+ $[38] = t11;
14084
+ $[39] = t15;
14085
+ $[40] = t16;
13286
14086
  } else {
13287
- t4 = $[6];
14087
+ t16 = $[40];
13288
14088
  }
13289
- const updateSearchResults = t4;
13290
- let T0;
13291
- let additionalPluginChildrenEnd;
13292
- let additionalPluginSections;
13293
- let t10;
13294
- let t11;
13295
- let t12;
13296
- let t13;
13297
- let t5;
13298
- let t6;
13299
- let t7;
13300
- let t8;
13301
- let t9;
13302
- if ($[7] !== additionalActions || $[8] !== additionalChildrenStart || $[9] !== containerRef || $[10] !== context || $[11] !== customizationController.plugins || $[12] !== direction || $[13] !== filteredNavigationEntries || $[14] !== filteredUrls || $[15] !== groups || $[16] !== performingSearch) {
13303
- const filteredGroups = filteredUrls ? filteredNavigationEntries.map(_temp2$5) : [];
13304
- const allGroups = filteredUrls ? filteredGroups.filter((group, index) => filteredGroups.indexOf(group) === index) : [...groups];
13305
- if (filteredNavigationEntries.filter(_temp3$3).length > 0 || filteredNavigationEntries.length === 0) {
13306
- allGroups.push(void 0);
13307
- }
13308
- let additionalPluginChildrenStart;
13309
- if (customizationController.plugins) {
13310
- let t143;
13311
- if ($[29] !== context || $[30] !== customizationController.plugins) {
13312
- const sectionProps = {
13313
- context
13314
- };
13315
- t143 = customizationController.plugins.filter(_temp4$2).map((plugin_0, i) => {
13316
- const section = plugin_0.homePage.includeSection(sectionProps);
13317
- return /* @__PURE__ */ jsx(NavigationGroup, { group: section.title, children: section.children }, `plugin_section_${plugin_0.key}`);
13318
- });
13319
- $[29] = context;
13320
- $[30] = customizationController.plugins;
13321
- $[31] = t143;
13322
- } else {
13323
- t143 = $[31];
13324
- }
13325
- let t153;
13326
- if ($[32] !== t143) {
13327
- t153 = /* @__PURE__ */ jsx(Fragment, { children: t143 });
13328
- $[32] = t143;
13329
- $[33] = t153;
13330
- } else {
13331
- t153 = $[33];
13332
- }
13333
- additionalPluginSections = t153;
13334
- let t162;
13335
- if ($[34] !== customizationController.plugins) {
13336
- t162 = customizationController.plugins.filter(_temp5$2).map(_temp6$2);
13337
- $[34] = customizationController.plugins;
13338
- $[35] = t162;
13339
- } else {
13340
- t162 = $[35];
13341
- }
13342
- let t172;
13343
- if ($[36] !== t162) {
13344
- t172 = /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: t162 });
13345
- $[36] = t162;
13346
- $[37] = t172;
13347
- } else {
13348
- t172 = $[37];
13349
- }
13350
- additionalPluginChildrenStart = t172;
13351
- let t18;
13352
- if ($[38] !== customizationController.plugins) {
13353
- t18 = customizationController.plugins.filter(_temp7$1).map(_temp8);
13354
- $[38] = customizationController.plugins;
13355
- $[39] = t18;
13356
- } else {
13357
- t18 = $[39];
13358
- }
13359
- let t19;
13360
- if ($[40] !== t18) {
13361
- t19 = /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: t18 });
13362
- $[40] = t18;
13363
- $[41] = t19;
13364
- } else {
13365
- t19 = $[41];
13366
- }
13367
- additionalPluginChildrenEnd = t19;
13368
- }
13369
- t11 = "home_page";
13370
- t12 = containerRef;
13371
- t13 = "py-2 overflow-auto h-full w-full";
13372
- T0 = Container;
13373
- t5 = "6xl";
13374
- const t142 = direction === "down" ? -84 : 0;
13375
- let t152;
13376
- if ($[42] !== t142) {
13377
- t152 = {
13378
- top: t142
13379
- };
13380
- $[42] = t142;
13381
- $[43] = t152;
14089
+ return t16;
14090
+ }
14091
+ const DEFAULT_GROUP_NAME = "Views";
14092
+ const ADMIN_GROUP_NAME = "Admin";
14093
+ function DefaultHomePage({
14094
+ additionalActions,
14095
+ additionalChildrenStart,
14096
+ additionalChildrenEnd
14097
+ }) {
14098
+ const context = useFireCMSContext();
14099
+ const customizationController = useCustomizationController();
14100
+ const navigationController = useNavigationController();
14101
+ if (!navigationController.topLevelNavigation) throw Error("Navigation not ready");
14102
+ const {
14103
+ allowDragAndDrop,
14104
+ navigationEntries: rawNavigationEntries,
14105
+ groups: groupOrderFromNavController,
14106
+ onNavigationEntriesUpdate
14107
+ } = navigationController.topLevelNavigation;
14108
+ const fuse = useRef(null);
14109
+ const [filteredUrls, setFilteredUrls] = useState(null);
14110
+ const performingSearch = Boolean(filteredUrls);
14111
+ const filteredNavigationEntries = filteredUrls ? rawNavigationEntries.filter((e) => filteredUrls.includes(e.url)) : rawNavigationEntries;
14112
+ useEffect(() => {
14113
+ fuse.current = new Fuse(rawNavigationEntries, {
14114
+ keys: ["name", "description", "group", "path"]
14115
+ });
14116
+ }, [rawNavigationEntries]);
14117
+ const updateSearch = useCallback((v) => {
14118
+ if (!v?.trim()) return setFilteredUrls(null);
14119
+ const r = fuse.current?.search(v.trim());
14120
+ setFilteredUrls(r ? r.map((x) => x.item.url) : []);
14121
+ }, []);
14122
+ const [items, setItems] = useState([]);
14123
+ const [adminGroupData, setAdminGroupData] = useState(null);
14124
+ useEffect(() => {
14125
+ const src = performingSearch ? filteredNavigationEntries : rawNavigationEntries;
14126
+ const entriesByGroup = {};
14127
+ src.forEach((e_0) => {
14128
+ const g = e_0.type === "admin" ? ADMIN_GROUP_NAME : e_0.group ?? DEFAULT_GROUP_NAME;
14129
+ (entriesByGroup[g] ??= []).push(e_0);
14130
+ });
14131
+ let allProcessed;
14132
+ if (performingSearch) {
14133
+ const ordered = [...new Set(src.map((e_1) => e_1.group ?? DEFAULT_GROUP_NAME))];
14134
+ allProcessed = ordered.map((name) => ({
14135
+ name,
14136
+ entries: entriesByGroup[name] || []
14137
+ })).filter((g_0) => g_0.entries.length);
13382
14138
  } else {
13383
- t152 = $[43];
14139
+ allProcessed = groupOrderFromNavController.map((g_1) => ({
14140
+ name: g_1,
14141
+ entries: entriesByGroup[g_1] || []
14142
+ }));
14143
+ Object.keys(entriesByGroup).forEach((g_2) => {
14144
+ if (!groupOrderFromNavController.includes(g_2)) allProcessed.push({
14145
+ name: g_2,
14146
+ entries: entriesByGroup[g_2]
14147
+ });
14148
+ });
14149
+ allProcessed = allProcessed.filter((g_3) => g_3.entries.length || groupOrderFromNavController.includes(g_3.name));
13384
14150
  }
13385
- let t16;
13386
- if ($[44] === Symbol.for("react.memo_cache_sentinel")) {
13387
- t16 = /* @__PURE__ */ jsx(SearchBar, { onTextSearch: updateSearchResults, placeholder: "Search collections", large: false, autoFocus: true, innerClassName: "w-full", className: "w-full flex-grow" });
13388
- $[44] = t16;
14151
+ const admin = allProcessed.find((g_4) => g_4.name === ADMIN_GROUP_NAME);
14152
+ if (admin) {
14153
+ setAdminGroupData(admin);
14154
+ setItems(allProcessed.filter((g_5) => g_5.name !== ADMIN_GROUP_NAME));
13389
14155
  } else {
13390
- t16 = $[44];
14156
+ setAdminGroupData(null);
14157
+ setItems(allProcessed);
13391
14158
  }
13392
- if ($[45] !== additionalActions || $[46] !== t152) {
13393
- t6 = /* @__PURE__ */ jsxs("div", { className: "w-full sticky py-4 transition-all duration-400 ease-in-out top-0 z-10 flex flex-row gap-4", style: t152, children: [
13394
- t16,
14159
+ }, [performingSearch, filteredNavigationEntries, rawNavigationEntries, groupOrderFromNavController]);
14160
+ const updateItems = (updater) => {
14161
+ setItems(updater);
14162
+ };
14163
+ const persistNavigationGroups = (latest) => {
14164
+ const draggable = latest.map((g_6) => ({
14165
+ name: g_6.name,
14166
+ entries: g_6.entries.map((e_2) => e_2.path)
14167
+ }));
14168
+ const all = adminGroupData ? [...draggable, {
14169
+ name: adminGroupData.name,
14170
+ entries: adminGroupData.entries.map((e_3) => e_3.path)
14171
+ }] : draggable;
14172
+ onNavigationEntriesUpdate(all);
14173
+ };
14174
+ const {
14175
+ sensors,
14176
+ collisionDetection,
14177
+ onDragStart,
14178
+ onDragOver,
14179
+ onDragEnd,
14180
+ dropAnimation,
14181
+ activeItemForOverlay,
14182
+ activeGroupData,
14183
+ draggingGroupId,
14184
+ containers,
14185
+ dndKitActiveNode,
14186
+ onDragCancel,
14187
+ isDraggingCardOnly,
14188
+ dialogOpenForGroup,
14189
+ setDialogOpenForGroup,
14190
+ handleRenameGroup,
14191
+ isHoveringNewGroupDropZone,
14192
+ setIsHoveringNewGroupDropZone
14193
+ } = useHomePageDnd({
14194
+ items,
14195
+ setItems: updateItems,
14196
+ disabled: !allowDragAndDrop || performingSearch,
14197
+ onPersist: persistNavigationGroups,
14198
+ // ——► persistence here
14199
+ onGroupMoved: (g_7) => context.analyticsController?.onAnalyticsEvent?.("home_move_group", {
14200
+ name: g_7
14201
+ }),
14202
+ onCardMovedBetweenGroups: (card) => context.analyticsController?.onAnalyticsEvent?.("home_move_card", {
14203
+ id: card.id
14204
+ }),
14205
+ onNewGroupDrop: () => context.analyticsController?.onAnalyticsEvent?.("home_drop_new_group")
14206
+ });
14207
+ const {
14208
+ containerRef,
14209
+ direction
14210
+ } = useRestoreScroll();
14211
+ const dndDisabled = !allowDragAndDrop || performingSearch;
14212
+ const dndModifiers = useMemo(() => {
14213
+ if (dndKitActiveNode?.data.current?.type === "group") return [restrictToVerticalAxis, restrictToWindowEdges];
14214
+ return [restrictToWindowEdges];
14215
+ }, [dndKitActiveNode]);
14216
+ let additionalPluginChildrenStart;
14217
+ let additionalPluginChildrenEnd;
14218
+ let additionalPluginSections;
14219
+ if (customizationController.plugins) {
14220
+ const sectionProps = {
14221
+ context
14222
+ };
14223
+ additionalPluginSections = /* @__PURE__ */ jsx(Fragment, { children: customizationController.plugins.filter((p) => p.homePage?.includeSection).map((plugin) => {
14224
+ const section = plugin.homePage.includeSection(sectionProps);
14225
+ return /* @__PURE__ */ jsx(NavigationGroup, { group: section.title, children: section.children }, `plugin_section_${plugin.key}`);
14226
+ }) });
14227
+ additionalPluginChildrenStart = /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: customizationController.plugins.filter((p_0) => p_0.homePage?.additionalChildrenStart).map((plugin_0, i) => /* @__PURE__ */ jsx("div", { children: plugin_0.homePage.additionalChildrenStart }, `plugin_children_start_${i}`)) });
14228
+ additionalPluginChildrenEnd = /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: customizationController.plugins.filter((p_1) => p_1.homePage?.additionalChildrenEnd).map((plugin_1, i_0) => /* @__PURE__ */ jsx("div", { children: plugin_1.homePage.additionalChildrenEnd }, `plugin_children_end_${i_0}`)) });
14229
+ }
14230
+ return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: "py-2 overflow-auto h-full w-full", children: [
14231
+ /* @__PURE__ */ jsxs(Container, { maxWidth: "6xl", children: [
14232
+ /* @__PURE__ */ jsxs("div", { className: "w-full sticky py-4 transition-all duration-400 ease-in-out top-0 z-10 flex flex-row gap-4", style: {
14233
+ top: direction === "down" ? -84 : 0
14234
+ }, children: [
14235
+ /* @__PURE__ */ jsx(SearchBar, { onTextSearch: updateSearch, placeholder: "Search collections", autoFocus: true, innerClassName: "w-full", className: "w-full flex-grow" }),
13395
14236
  additionalActions
13396
- ] });
13397
- $[45] = additionalActions;
13398
- $[46] = t152;
13399
- $[47] = t6;
13400
- } else {
13401
- t6 = $[47];
13402
- }
13403
- if ($[48] !== performingSearch) {
13404
- t7 = /* @__PURE__ */ jsx(FavouritesView, { hidden: performingSearch });
13405
- $[48] = performingSearch;
13406
- $[49] = t7;
13407
- } else {
13408
- t7 = $[49];
13409
- }
13410
- t8 = additionalChildrenStart;
13411
- t9 = additionalPluginChildrenStart;
13412
- let t17;
13413
- if ($[50] !== context || $[51] !== customizationController.plugins || $[52] !== filteredNavigationEntries || $[53] !== performingSearch) {
13414
- t17 = (group_0, index_0) => {
13415
- const AdditionalCards = [];
13416
- const actionProps = {
13417
- group: group_0,
13418
- context
13419
- };
13420
- if (customizationController.plugins) {
13421
- customizationController.plugins.forEach((plugin_5) => {
13422
- if (plugin_5.homePage?.AdditionalCards) {
13423
- AdditionalCards.push(...toArray(plugin_5.homePage?.AdditionalCards));
13424
- }
13425
- });
13426
- }
13427
- const thisGroupCollections = filteredNavigationEntries.filter((entry_0) => entry_0.group === group_0 || !entry_0.group && group_0 === void 0);
13428
- if (thisGroupCollections.length === 0 && (AdditionalCards.length === 0 || performingSearch)) {
13429
- return null;
14237
+ ] }),
14238
+ /* @__PURE__ */ jsx(FavouritesView, { hidden: performingSearch }),
14239
+ additionalChildrenStart,
14240
+ additionalPluginChildrenStart,
14241
+ /* @__PURE__ */ jsxs(DndContext, { sensors, collisionDetection, measuring: {
14242
+ droppable: {
14243
+ strategy: MeasuringStrategy.Always,
14244
+ frequency: 500
13430
14245
  }
13431
- return /* @__PURE__ */ jsx(NavigationGroup, { group: group_0, children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4", children: [
13432
- thisGroupCollections.map((entry_1) => /* @__PURE__ */ jsx("div", { className: "col-span-1", children: /* @__PURE__ */ jsx(NavigationCardBinding, { ...entry_1, onClick: () => {
13433
- let event;
13434
- if (entry_1.type === "collection") {
13435
- event = "home_navigate_to_collection";
13436
- } else {
13437
- if (entry_1.type === "view") {
13438
- event = "home_navigate_to_view";
13439
- } else {
13440
- if (entry_1.type === "admin") {
13441
- event = "home_navigate_to_admin_view";
13442
- } else {
13443
- event = "unmapped_event";
13444
- }
13445
- }
13446
- }
13447
- context.analyticsController?.onAnalyticsEvent?.(event, {
13448
- path: entry_1.path
13449
- });
13450
- } }) }, `nav_${entry_1.group}_${entry_1.path}_${entry_1.name}`)),
13451
- group_0?.toLowerCase() !== "admin" && AdditionalCards && AdditionalCards.map((AdditionalCard, i_2) => /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(AdditionalCard, { ...actionProps }) }, `nav_${group_0}_add_${i_2}`))
13452
- ] }) }, `plugin_section_${group_0}`);
13453
- };
13454
- $[50] = context;
13455
- $[51] = customizationController.plugins;
13456
- $[52] = filteredNavigationEntries;
13457
- $[53] = performingSearch;
13458
- $[54] = t17;
13459
- } else {
13460
- t17 = $[54];
13461
- }
13462
- t10 = allGroups.map(t17);
13463
- $[7] = additionalActions;
13464
- $[8] = additionalChildrenStart;
13465
- $[9] = containerRef;
13466
- $[10] = context;
13467
- $[11] = customizationController.plugins;
13468
- $[12] = direction;
13469
- $[13] = filteredNavigationEntries;
13470
- $[14] = filteredUrls;
13471
- $[15] = groups;
13472
- $[16] = performingSearch;
13473
- $[17] = T0;
13474
- $[18] = additionalPluginChildrenEnd;
13475
- $[19] = additionalPluginSections;
13476
- $[20] = t10;
13477
- $[21] = t11;
13478
- $[22] = t12;
13479
- $[23] = t13;
13480
- $[24] = t5;
13481
- $[25] = t6;
13482
- $[26] = t7;
13483
- $[27] = t8;
13484
- $[28] = t9;
13485
- } else {
13486
- T0 = $[17];
13487
- additionalPluginChildrenEnd = $[18];
13488
- additionalPluginSections = $[19];
13489
- t10 = $[20];
13490
- t11 = $[21];
13491
- t12 = $[22];
13492
- t13 = $[23];
13493
- t5 = $[24];
13494
- t6 = $[25];
13495
- t7 = $[26];
13496
- t8 = $[27];
13497
- t9 = $[28];
13498
- }
13499
- let t14;
13500
- if ($[55] !== T0 || $[56] !== additionalChildrenEnd || $[57] !== additionalPluginChildrenEnd || $[58] !== additionalPluginSections || $[59] !== t10 || $[60] !== t5 || $[61] !== t6 || $[62] !== t7 || $[63] !== t8 || $[64] !== t9) {
13501
- t14 = /* @__PURE__ */ jsxs(T0, { maxWidth: t5, children: [
13502
- t6,
13503
- t7,
13504
- t8,
13505
- t9,
13506
- t10,
14246
+ }, onDragStart, onDragOver, onDragEnd, onDragCancel, modifiers: dndModifiers, children: [
14247
+ /* @__PURE__ */ jsx(SortableContext, { items: containers, strategy: verticalListSortingStrategy, children: items.map((groupData) => {
14248
+ const groupKey = groupData.name;
14249
+ const entriesInGroup = groupData.entries;
14250
+ const AdditionalCards = [];
14251
+ customizationController.plugins?.forEach((p_2) => {
14252
+ if (p_2.homePage?.AdditionalCards) AdditionalCards.push(...toArray(p_2.homePage.AdditionalCards));
14253
+ });
14254
+ const actionProps = {
14255
+ group: groupKey === DEFAULT_GROUP_NAME ? void 0 : groupKey,
14256
+ context
14257
+ };
14258
+ if (entriesInGroup.length === 0 && (AdditionalCards.length === 0 || performingSearch) && !groupOrderFromNavController.includes(groupKey)) return null;
14259
+ return /* @__PURE__ */ jsx(SortableNavigationGroup, { groupName: groupKey, disabled: dndDisabled, children: /* @__PURE__ */ jsx(NavigationGroup, { group: groupKey === DEFAULT_GROUP_NAME ? void 0 : groupKey, minimised: draggingGroupId === groupKey && !isDraggingCardOnly, isPotentialCardDropTarget: isDraggingCardOnly, dndDisabled, onEditGroup: () => {
14260
+ if (dndDisabled) return;
14261
+ setDialogOpenForGroup(groupKey);
14262
+ }, children: /* @__PURE__ */ jsx(NavigationGroupDroppable, { id: groupKey, itemIds: entriesInGroup.map((e_4) => e_4.url), isPotentialCardDropTarget: isDraggingCardOnly, children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 ", children: [
14263
+ entriesInGroup.map((entry) => /* @__PURE__ */ jsx(SortableNavigationCard, { entry, onClick: () => {
14264
+ let event = "unmapped_event";
14265
+ if (entry.type === "collection") event = "home_navigate_to_collection";
14266
+ else if (entry.type === "view") event = "home_navigate_to_view";
14267
+ else if (entry.type === "admin") event = "home_navigate_to_admin_view";
14268
+ context.analyticsController?.onAnalyticsEvent?.(event, {
14269
+ path: entry.path
14270
+ });
14271
+ } }, entry.url)),
14272
+ !performingSearch && groupKey.toLowerCase() !== ADMIN_GROUP_NAME.toLowerCase() && AdditionalCards.map((C, i_1) => /* @__PURE__ */ jsx(C, { ...actionProps }, `extra_${groupKey}_${i_1}`))
14273
+ ] }) }) }) }, groupKey);
14274
+ }) }, JSON.stringify(containers)),
14275
+ /* @__PURE__ */ jsx(NewGroupDropZone, { disabled: dndDisabled, setIsHovering: setIsHoveringNewGroupDropZone }),
14276
+ /* @__PURE__ */ jsx(DragOverlay, { adjustScale: false, dropAnimation, children: activeGroupData && draggingGroupId === activeGroupData.name ? /* @__PURE__ */ jsx("div", { className: "rounded-lg bg-transparent", style: {
14277
+ padding: 0,
14278
+ margin: 0
14279
+ }, children: /* @__PURE__ */ jsx(NavigationGroup, { group: activeGroupData.name === DEFAULT_GROUP_NAME ? void 0 : activeGroupData.name, isPreview: false, minimised: true }) }) : activeItemForOverlay ? /* @__PURE__ */ jsx(NavigationCardBinding, { ...activeItemForOverlay, shrink: isHoveringNewGroupDropZone }) : null })
14280
+ ] }),
14281
+ !performingSearch && adminGroupData && /* @__PURE__ */ jsx(NavigationGroup, { group: adminGroupData.name, children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 ", children: adminGroupData.entries.map((entry_0) => /* @__PURE__ */ jsx(NavigationCardBinding, { ...entry_0, onClick: () => {
14282
+ let event_0 = "unmapped_event";
14283
+ if (entry_0.type === "collection") event_0 = "home_navigate_to_collection";
14284
+ else if (entry_0.type === "view") event_0 = "home_navigate_to_view";
14285
+ else if (entry_0.type === "admin") event_0 = "home_navigate_to_admin_view";
14286
+ context.analyticsController?.onAnalyticsEvent?.(event_0, {
14287
+ path: entry_0.path
14288
+ });
14289
+ } }, entry_0.url)) }) }),
13507
14290
  additionalPluginSections,
13508
14291
  additionalPluginChildrenEnd,
13509
14292
  additionalChildrenEnd
13510
- ] });
13511
- $[55] = T0;
13512
- $[56] = additionalChildrenEnd;
13513
- $[57] = additionalPluginChildrenEnd;
13514
- $[58] = additionalPluginSections;
13515
- $[59] = t10;
13516
- $[60] = t5;
13517
- $[61] = t6;
13518
- $[62] = t7;
13519
- $[63] = t8;
13520
- $[64] = t9;
13521
- $[65] = t14;
13522
- } else {
13523
- t14 = $[65];
13524
- }
13525
- let t15;
13526
- if ($[66] !== t11 || $[67] !== t12 || $[68] !== t13 || $[69] !== t14) {
13527
- t15 = /* @__PURE__ */ jsx("div", { id: t11, ref: t12, className: t13, children: t14 });
13528
- $[66] = t11;
13529
- $[67] = t12;
13530
- $[68] = t13;
13531
- $[69] = t14;
13532
- $[70] = t15;
13533
- } else {
13534
- t15 = $[70];
13535
- }
13536
- return t15;
13537
- }
13538
- function _temp8(plugin_4, i_1) {
13539
- return /* @__PURE__ */ jsx("div", { children: plugin_4.homePage.additionalChildrenEnd }, `plugin_children_start_${i_1}`);
13540
- }
13541
- function _temp7$1(plugin_3) {
13542
- return plugin_3.homePage?.additionalChildrenEnd;
13543
- }
13544
- function _temp6$2(plugin_2, i_0) {
13545
- return /* @__PURE__ */ jsx("div", { children: plugin_2.homePage.additionalChildrenStart }, `plugin_children_start_${i_0}`);
13546
- }
13547
- function _temp5$2(plugin_1) {
13548
- return plugin_1.homePage?.additionalChildrenStart;
13549
- }
13550
- function _temp4$2(plugin) {
13551
- return plugin.homePage?.includeSection;
13552
- }
13553
- function _temp3$3(e_1) {
13554
- return !e_1.group;
13555
- }
13556
- function _temp2$5(entry) {
13557
- return entry.group;
13558
- }
13559
- function _temp$c(e_0) {
13560
- return e_0.item.url;
14293
+ ] }),
14294
+ dialogOpenForGroup && /* @__PURE__ */ jsx(RenameGroupDialog, { open: true, initialName: dialogOpenForGroup, existingGroupNames: items.map((g_8) => g_8.name).filter((n) => n !== dialogOpenForGroup), onClose: () => setDialogOpenForGroup(null), onRename: (newName) => {
14295
+ handleRenameGroup(dialogOpenForGroup, newName);
14296
+ setDialogOpenForGroup(null);
14297
+ } })
14298
+ ] });
13561
14299
  }
13562
14300
  function EntityCollectionViewActions(t0) {
13563
14301
  const $ = c(41);
@@ -16532,6 +17270,92 @@ function ReferenceFieldBindingInternal({
16532
17270
  /* @__PURE__ */ jsx(FieldHelperText, { includeDescription, showError, error, disabled, property })
16533
17271
  ] });
16534
17272
  }
17273
+ function ReferenceAsStringFieldBinding(props) {
17274
+ const $ = c(4);
17275
+ if (typeof props.property.reference?.path !== "string") {
17276
+ let t02;
17277
+ if ($[0] !== props) {
17278
+ t02 = /* @__PURE__ */ jsx(ReadOnlyFieldBinding, { ...props });
17279
+ $[0] = props;
17280
+ $[1] = t02;
17281
+ } else {
17282
+ t02 = $[1];
17283
+ }
17284
+ return t02;
17285
+ }
17286
+ let t0;
17287
+ if ($[2] !== props) {
17288
+ t0 = /* @__PURE__ */ jsx(ReferenceAsStringFieldBindingInternal, { ...props });
17289
+ $[2] = props;
17290
+ $[3] = t0;
17291
+ } else {
17292
+ t0 = $[3];
17293
+ }
17294
+ return t0;
17295
+ }
17296
+ function ReferenceAsStringFieldBindingInternal({
17297
+ propertyKey,
17298
+ value,
17299
+ setValue,
17300
+ error,
17301
+ showError,
17302
+ isSubmitting,
17303
+ disabled,
17304
+ minimalistView,
17305
+ property,
17306
+ includeDescription,
17307
+ size = "medium"
17308
+ }) {
17309
+ if (!property.reference?.path) {
17310
+ throw new Error("Property path is required for ReferenceAsStringFieldBinding");
17311
+ }
17312
+ useClearRestoreValue({
17313
+ property,
17314
+ value,
17315
+ setValue
17316
+ });
17317
+ const navigationController = useNavigationController();
17318
+ const path = property.reference.path;
17319
+ const collection = useMemo(() => {
17320
+ return path ? navigationController.getCollection(path) : void 0;
17321
+ }, [path]);
17322
+ const referenceValue = useMemo(() => {
17323
+ if (value && path) {
17324
+ return new EntityReference(value, path);
17325
+ }
17326
+ return void 0;
17327
+ }, [value, path]);
17328
+ if (!collection) {
17329
+ throw Error(`Couldn't find the corresponding collection for the path: ${path}`);
17330
+ }
17331
+ const onSingleEntitySelected = useCallback((e) => {
17332
+ setValue(e ? e.id : null);
17333
+ }, [setValue]);
17334
+ const referenceDialogController = useReferenceDialog({
17335
+ multiselect: false,
17336
+ path,
17337
+ collection,
17338
+ onSingleEntitySelected,
17339
+ selectedEntityIds: value ? [value] : void 0,
17340
+ forceFilter: property.reference.forceFilter
17341
+ });
17342
+ const onEntryClick = (e_0) => {
17343
+ e_0.preventDefault();
17344
+ referenceDialogController.open();
17345
+ };
17346
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
17347
+ !minimalistView && /* @__PURE__ */ jsx(LabelWithIconAndTooltip, { propertyKey, icon: getIconForProperty(property, "small"), required: property.validation?.required, title: property.name, className: "h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5" }),
17348
+ !collection && /* @__PURE__ */ jsx(ErrorView, { error: "The specified collection does not exist. Check console" }),
17349
+ collection && /* @__PURE__ */ jsxs(Fragment, { children: [
17350
+ referenceValue && /* @__PURE__ */ jsx(ReferencePreview, { disabled: !path, previewProperties: property.reference?.previewProperties, hover: !disabled, size, onClick: disabled || isSubmitting ? void 0 : onEntryClick, reference: referenceValue, includeEntityLink: property.reference?.includeEntityLink, includeId: property.reference?.includeId }),
17351
+ !value && /* @__PURE__ */ jsx("div", { className: "justify-center text-left", children: /* @__PURE__ */ jsxs(EntityPreviewContainer, { className: cls("px-6 h-16 text-sm font-medium flex items-center gap-6", disabled || isSubmitting ? "text-surface-accent-500" : "cursor-pointer text-surface-accent-700 dark:text-surface-accent-300 hover:bg-surface-accent-50 dark:hover:bg-surface-800 group-hover:bg-surface-accent-50 dark:group-hover:bg-surface-800"), onClick: onEntryClick, size: "medium", children: [
17352
+ /* @__PURE__ */ jsx(IconForView, { collectionOrView: collection, className: "text-surface-300 dark:text-surface-600" }),
17353
+ `Edit ${property.name}`.toUpperCase()
17354
+ ] }) })
17355
+ ] }),
17356
+ /* @__PURE__ */ jsx(FieldHelperText, { includeDescription, showError, error, disabled, property })
17357
+ ] });
17358
+ }
16535
17359
  const PropertyFieldBinding = React__default.memo(PropertyFieldBindingInternal, (a, b) => {
16536
17360
  if (a.propertyKey !== b.propertyKey) {
16537
17361
  return false;
@@ -17774,7 +18598,6 @@ function RepeatFieldBinding(t0) {
17774
18598
  minimalistView: false,
17775
18599
  autoFocus: internalId === lastAddedId
17776
18600
  };
17777
- console.debug("Building entry for", index, fieldProps);
17778
18601
  return /* @__PURE__ */ jsx(ErrorBoundary, { children: /* @__PURE__ */ jsx(PropertyFieldBinding, { ...fieldProps, index }) });
17779
18602
  };
17780
18603
  $[4] = context;
@@ -20568,6 +21391,8 @@ function getParentReferencesFromPath(props) {
20568
21391
  }
20569
21392
  const DEFAULT_BASE_PATH = "/";
20570
21393
  const DEFAULT_COLLECTION_PATH = "/c";
21394
+ const NAVIGATION_DEFAULT_GROUP_NAME = "Views";
21395
+ const NAVIGATION_ADMIN_GROUP_NAME = "Admin";
20571
21396
  function useBuildNavigationController(props) {
20572
21397
  const {
20573
21398
  basePath = DEFAULT_BASE_PATH,
@@ -20581,12 +21406,14 @@ function useBuildNavigationController(props) {
20581
21406
  plugins,
20582
21407
  userConfigPersistence,
20583
21408
  dataSourceDelegate,
20584
- disabled
21409
+ disabled,
21410
+ navigationGroupMappings
20585
21411
  } = props;
20586
21412
  const navigate = useNavigate();
20587
21413
  const collectionsRef = useRef();
20588
21414
  const viewsRef = useRef();
20589
21415
  const adminViewsRef = useRef();
21416
+ const navigationEntriesOrderRef = useRef();
20590
21417
  const [initialised, setInitialised] = useState(false);
20591
21418
  const [topLevelNavigation, setTopLevelNavigation] = useState(void 0);
20592
21419
  const [navigationLoading, setNavigationLoading] = useState(true);
@@ -20597,80 +21424,127 @@ function useBuildNavigationController(props) {
20597
21424
  const fullCollectionPath = cleanBasePath ? `/${cleanBasePath}/${cleanBaseCollectionPath}` : `/${cleanBaseCollectionPath}`;
20598
21425
  const buildCMSUrlPath = useCallback((path) => cleanBasePath ? `/${cleanBasePath}/${encodePath(path)}` : `/${encodePath(path)}`, [cleanBasePath]);
20599
21426
  const buildUrlCollectionPath = useCallback((path_0) => `${removeInitialAndTrailingSlashes(baseCollectionPath)}/${encodePath(path_0)}`, [baseCollectionPath]);
21427
+ const allPluginGroups = plugins?.flatMap((plugin) => plugin.homePage?.navigationEntries ? plugin.homePage.navigationEntries.map((e) => e.name) : []) ?? [];
21428
+ const pluginGroups = [...new Set(allPluginGroups)];
21429
+ const onNavigationEntriesOrderUpdate = useCallback((entries) => {
21430
+ if (!plugins) {
21431
+ return;
21432
+ }
21433
+ const filteredEntries = entries.filter((entry) => entry.entries.length > 0);
21434
+ if (plugins.some((plugin_1) => plugin_1.homePage?.onNavigationEntriesUpdate)) {
21435
+ plugins.forEach((plugin_0) => {
21436
+ if (plugin_0.homePage?.onNavigationEntriesUpdate) {
21437
+ plugin_0.homePage.onNavigationEntriesUpdate(filteredEntries);
21438
+ }
21439
+ });
21440
+ }
21441
+ }, [plugins]);
20600
21442
  const computeTopNavigation = useCallback((collections, views, adminViews, viewsOrder_0) => {
20601
- let navigationEntries = [...(collections ?? []).map((collection) => !collection.hideFromNavigation ? {
20602
- url: buildUrlCollectionPath(collection.id ?? collection.path),
20603
- type: "collection",
20604
- name: collection.name.trim(),
20605
- path: collection.id ?? collection.path,
20606
- collection,
20607
- description: collection.description?.trim(),
20608
- group: getGroup(collection)
20609
- } : void 0).filter(Boolean), ...(views ?? []).map((view) => !view.hideFromNavigation ? {
20610
- url: buildCMSUrlPath(Array.isArray(view.path) ? view.path[0] : view.path),
20611
- name: view.name.trim(),
20612
- type: "view",
20613
- path: view.path,
20614
- view,
20615
- description: view.description?.trim(),
20616
- group: getGroup(view)
20617
- } : void 0).filter(Boolean), ...(adminViews ?? []).map((view_0) => !view_0.hideFromNavigation ? {
20618
- url: buildCMSUrlPath(Array.isArray(view_0.path) ? view_0.path[0] : view_0.path),
20619
- name: view_0.name.trim(),
20620
- type: "admin",
20621
- path: view_0.path,
20622
- view: view_0,
20623
- description: view_0.description?.trim(),
20624
- group: "Admin"
20625
- } : void 0).filter(Boolean)];
20626
- navigationEntries = navigationEntries.sort((a, b) => {
20627
- if (a.group !== "Views" && a.group !== "Admin" && (b.group === "Views" || b.group === "Admin")) {
20628
- return -1;
20629
- }
20630
- if (b.group !== "Views" && b.group !== "Admin" && (a.group === "Views" || a.group === "Admin")) {
20631
- return 1;
20632
- }
20633
- if (a.group === "Admin" && b.group !== "Admin") {
20634
- return 1;
20635
- }
20636
- if (a.group !== "Admin" && b.group === "Admin") {
20637
- return -1;
20638
- }
20639
- if (a.group === "Views" && b.group !== "Views") {
20640
- return -1;
21443
+ const finalNavigationGroupMappings = computeNavigationGroups({
21444
+ navigationGroupMappings,
21445
+ collections,
21446
+ views,
21447
+ plugins
21448
+ });
21449
+ const allPluginNavigationEntries = finalNavigationGroupMappings.map((g) => g.entries).flat() ?? [];
21450
+ const navigationEntriesOrder = [...new Set(allPluginNavigationEntries)];
21451
+ let navigationEntries = [...(collections ?? []).reduce((acc, collection) => {
21452
+ if (collection.hideFromNavigation) return acc;
21453
+ const pathKey = collection.id ?? collection.path;
21454
+ let groupName = getGroup(collection);
21455
+ if (finalNavigationGroupMappings) {
21456
+ for (const pluginGroupDef of finalNavigationGroupMappings) {
21457
+ if (pluginGroupDef.entries.includes(pathKey)) {
21458
+ groupName = pluginGroupDef.name;
21459
+ break;
21460
+ }
21461
+ }
20641
21462
  }
20642
- if (a.group !== "Views" && b.group === "Views") {
20643
- return 1;
21463
+ acc.push({
21464
+ id: `collection:${pathKey}`,
21465
+ url: buildUrlCollectionPath(pathKey),
21466
+ type: "collection",
21467
+ name: collection.name.trim(),
21468
+ path: pathKey,
21469
+ collection,
21470
+ description: collection.description?.trim(),
21471
+ group: groupName ?? NAVIGATION_DEFAULT_GROUP_NAME
21472
+ });
21473
+ return acc;
21474
+ }, []), ...(views ?? []).reduce((acc_0, view) => {
21475
+ if (view.hideFromNavigation) return acc_0;
21476
+ const pathKey_0 = Array.isArray(view.path) ? view.path[0] : view.path;
21477
+ let groupName_0 = getGroup(view);
21478
+ if (finalNavigationGroupMappings) {
21479
+ for (const pluginGroupDef_0 of finalNavigationGroupMappings) {
21480
+ if (pluginGroupDef_0.entries.includes(pathKey_0)) {
21481
+ groupName_0 = pluginGroupDef_0.name;
21482
+ break;
21483
+ }
21484
+ }
20644
21485
  }
21486
+ acc_0.push({
21487
+ id: `view:${pathKey_0}`,
21488
+ url: buildCMSUrlPath(pathKey_0),
21489
+ name: view.name.trim(),
21490
+ type: "view",
21491
+ path: view.path,
21492
+ view,
21493
+ description: view.description?.trim(),
21494
+ group: groupName_0 ?? NAVIGATION_DEFAULT_GROUP_NAME
21495
+ });
21496
+ return acc_0;
21497
+ }, []), ...(adminViews ?? []).reduce((acc_1, view_0) => {
21498
+ if (view_0.hideFromNavigation) return acc_1;
21499
+ const pathKey_1 = Array.isArray(view_0.path) ? view_0.path[0] : view_0.path;
21500
+ const groupName_1 = NAVIGATION_ADMIN_GROUP_NAME;
21501
+ acc_1.push({
21502
+ id: `admin:${pathKey_1}`,
21503
+ url: buildCMSUrlPath(pathKey_1),
21504
+ name: view_0.name.trim(),
21505
+ type: "admin",
21506
+ path: view_0.path,
21507
+ view: view_0,
21508
+ description: view_0.description?.trim(),
21509
+ group: groupName_1
21510
+ });
21511
+ return acc_1;
21512
+ }, [])];
21513
+ const groupOrderValue = (groupName_2) => {
21514
+ if (groupName_2 === NAVIGATION_ADMIN_GROUP_NAME) return 1;
20645
21515
  return 0;
21516
+ };
21517
+ navigationEntries = navigationEntries.sort((a, b) => {
21518
+ return groupOrderValue(a.group) - groupOrderValue(b.group);
20646
21519
  });
20647
- if (viewsOrder_0) {
21520
+ const usedViewsOrder = viewsOrder_0 ?? navigationEntriesOrder;
21521
+ if (usedViewsOrder) {
20648
21522
  navigationEntries = navigationEntries.sort((a_0, b_0) => {
20649
- const aIndex = viewsOrder_0.indexOf(a_0.path);
20650
- const bIndex = viewsOrder_0.indexOf(b_0.path);
20651
- if (aIndex === -1 && bIndex === -1) {
20652
- return 0;
20653
- }
20654
- if (aIndex === -1) {
20655
- return 1;
20656
- }
20657
- if (bIndex === -1) {
20658
- return -1;
20659
- }
21523
+ const getSortPath = (navEntry) => typeof navEntry.path === "string" ? navEntry.path : navEntry.path[0];
21524
+ const aIndex = usedViewsOrder.indexOf(getSortPath(a_0));
21525
+ const bIndex = usedViewsOrder.indexOf(getSortPath(b_0));
21526
+ if (aIndex === -1 && bIndex === -1) return 0;
21527
+ if (aIndex === -1) return 1;
21528
+ if (bIndex === -1) return -1;
20660
21529
  return aIndex - bIndex;
20661
21530
  });
20662
21531
  }
20663
- const groups = Object.values(navigationEntries).map((e) => e.group).filter(Boolean).filter((value, index, array) => array.indexOf(value) === index);
21532
+ const collectedGroupsFromEntries = navigationEntries.map((e_0) => e_0.group).filter(Boolean);
21533
+ const allDefinedGroups = [...pluginGroups, ...collectedGroupsFromEntries];
21534
+ const uniqueGroups = [...new Set(allDefinedGroups)].sort((a_1, b_1) => groupOrderValue(a_1) - groupOrderValue(b_1));
20664
21535
  return {
21536
+ allowDragAndDrop: plugins?.some((plugin_2) => plugin_2.homePage?.allowDragAndDrop) ?? false,
20665
21537
  navigationEntries,
20666
- groups
21538
+ groups: uniqueGroups,
21539
+ onNavigationEntriesUpdate: onNavigationEntriesOrderUpdate
20667
21540
  };
20668
- }, [buildCMSUrlPath, buildUrlCollectionPath]);
21541
+ }, [navigationGroupMappings, buildCMSUrlPath, buildUrlCollectionPath, pluginGroups, onNavigationEntriesOrderUpdate]);
20669
21542
  const refreshNavigation = useCallback(async () => {
20670
21543
  if (disabled || authController.initialLoading) return;
20671
21544
  console.debug("Refreshing navigation");
20672
21545
  try {
20673
21546
  const [resolvedCollections = [], resolvedViews, resolvedAdminViews = []] = await Promise.all([resolveCollections(collectionsProp, collectionPermissions, authController, dataSourceDelegate, plugins), resolveCMSViews(viewsProp, authController, dataSourceDelegate), resolveCMSViews(adminViewsProp, authController, dataSourceDelegate)]);
21547
+ const computedTopLevelNav = computeTopNavigation(resolvedCollections, resolvedViews, resolvedAdminViews, viewsOrder);
20674
21548
  let shouldUpdateTopLevelNav = false;
20675
21549
  if (!areCollectionListsEqual(collectionsRef.current ?? [], resolvedCollections)) {
20676
21550
  collectionsRef.current = resolvedCollections;
@@ -20689,13 +21563,17 @@ function useBuildNavigationController(props) {
20689
21563
  adminViewsRef.current = resolvedAdminViews;
20690
21564
  shouldUpdateTopLevelNav = true;
20691
21565
  }
20692
- const computedTopLevelNav = computeTopNavigation(resolvedCollections, resolvedViews, resolvedAdminViews, viewsOrder);
21566
+ const navigationEntriesOrder_0 = computedTopLevelNav.navigationEntries.map((e_2) => e_2.id);
21567
+ if (!equal(navigationEntriesOrderRef.current, navigationEntriesOrder_0)) {
21568
+ navigationEntriesOrderRef.current = navigationEntriesOrder_0;
21569
+ shouldUpdateTopLevelNav = true;
21570
+ }
20693
21571
  if (shouldUpdateTopLevelNav && !equal(topLevelNavigation, computedTopLevelNav)) {
20694
21572
  setTopLevelNavigation(computedTopLevelNav);
20695
21573
  }
20696
- } catch (e_0) {
20697
- console.error(e_0);
20698
- setNavigationLoadingError(e_0);
21574
+ } catch (e_1) {
21575
+ console.error(e_1);
21576
+ setNavigationLoadingError(e_1);
20699
21577
  }
20700
21578
  if (navigationLoading) setNavigationLoading(false);
20701
21579
  if (!initialised) setInitialised(true);
@@ -20895,9 +21773,9 @@ async function resolveCMSViews(baseViews, authController, dataSource) {
20895
21773
  function getGroup(collectionOrView) {
20896
21774
  const trimmed = collectionOrView.group?.trim();
20897
21775
  if (!trimmed || trimmed === "") {
20898
- return "Views";
21776
+ return NAVIGATION_DEFAULT_GROUP_NAME;
20899
21777
  }
20900
- return trimmed ?? "Views";
21778
+ return trimmed ?? NAVIGATION_DEFAULT_GROUP_NAME;
20901
21779
  }
20902
21780
  function areCollectionListsEqual(a, b) {
20903
21781
  if (a.length !== b.length) {
@@ -20923,6 +21801,58 @@ function areCollectionsEqual(a, b) {
20923
21801
  }
20924
21802
  return equal(removeFunctions(restA), removeFunctions(restB));
20925
21803
  }
21804
+ function computeNavigationGroups({
21805
+ navigationGroupMappings,
21806
+ collections,
21807
+ views,
21808
+ plugins
21809
+ }) {
21810
+ let result = navigationGroupMappings;
21811
+ result = plugins ? plugins?.reduce((acc, plugin) => {
21812
+ if (plugin.homePage?.navigationEntries) {
21813
+ plugin.homePage.navigationEntries.forEach((entry) => {
21814
+ const {
21815
+ name,
21816
+ entries
21817
+ } = entry;
21818
+ const existingGroup = acc.find((entry2) => entry2.name === name);
21819
+ if (existingGroup) {
21820
+ existingGroup.entries.push(...entries);
21821
+ } else {
21822
+ acc.push({
21823
+ name,
21824
+ entries: [...entries]
21825
+ });
21826
+ }
21827
+ });
21828
+ }
21829
+ return acc;
21830
+ }, [...result ?? []]) : result;
21831
+ if (!result) {
21832
+ result = [];
21833
+ const groupMap = {};
21834
+ (collections ?? []).forEach((collection) => {
21835
+ const name = getGroup(collection);
21836
+ const entry = collection.id ?? collection.path;
21837
+ if (!groupMap[name]) groupMap[name] = [];
21838
+ groupMap[name].push(entry);
21839
+ });
21840
+ (views ?? []).forEach((view) => {
21841
+ const name = getGroup(view);
21842
+ const entry = Array.isArray(view.path) ? view.path[0] : view.path;
21843
+ if (!groupMap[name]) groupMap[name] = [];
21844
+ groupMap[name].push(entry);
21845
+ });
21846
+ result = Object.entries(groupMap).map(([name, entries]) => ({
21847
+ name,
21848
+ entries
21849
+ }));
21850
+ }
21851
+ result.forEach((group) => {
21852
+ group.entries = [...new Set(group.entries)];
21853
+ });
21854
+ return result;
21855
+ }
20926
21856
  function useBuildLocalConfigurationPersistence() {
20927
21857
  const $ = c(15);
20928
21858
  let t0;
@@ -22893,7 +23823,7 @@ function DrawerNavigationItem(t0) {
22893
23823
  const {
22894
23824
  isActive
22895
23825
  } = t52;
22896
- return cls("rounded-lg truncate", "hover:bg-surface-accent-300 hover:bg-opacity-75 dark:hover:bg-surface-accent-800 dark:hover:bg-opacity-75 text-text-primary dark:text-surface-200 hover:text-surface-900 hover:dark:text-white", "flex flex-row items-center mr-8", drawerOpen ? "pl-4 h-12" : "pl-4 h-11", "font-semibold text-xs", isActive ? "bg-surface-accent-200 bg-opacity-60 dark:bg-surface-800 dark:bg-opacity-50" : "");
23826
+ return cls("rounded-lg truncate", "hover:bg-surface-accent-300 hover:bg-opacity-75 dark:hover:bg-surface-accent-800 dark:hover:bg-opacity-75 text-text-primary dark:text-surface-200 hover:text-surface-900 hover:dark:text-white", "flex flex-row items-center mr-8", drawerOpen ? "pl-4 h-10" : "pl-4 h-9", "font-semibold text-xs", isActive ? "bg-surface-accent-200 bg-opacity-60 dark:bg-surface-800 dark:bg-opacity-50" : "");
22897
23827
  };
22898
23828
  $[4] = drawerOpen;
22899
23829
  $[5] = t4;
@@ -23053,7 +23983,7 @@ function DefaultDrawer(t0) {
23053
23983
  if ($[41] !== adminMenuOpen || $[42] !== buildGroupHeader || $[43] !== drawerOpen || $[44] !== navigationEntries || $[45] !== onClick || $[46] !== tooltipsOpen) {
23054
23984
  t10 = (group_0) => /* @__PURE__ */ jsxs("div", { className: "bg-surface-50 dark:bg-surface-800 dark:bg-opacity-30 my-4 rounded-lg ml-3 mr-1", children: [
23055
23985
  buildGroupHeader(group_0),
23056
- Object.values(navigationEntries).filter((e_0) => e_0.group === group_0).map((view_0, index) => /* @__PURE__ */ jsx(DrawerNavigationItem, { icon: /* @__PURE__ */ jsx(IconForView, { collectionOrView: view_0.collection ?? view_0.view, size: "small" }), tooltipsOpen, adminMenuOpen, drawerOpen, onClick: () => onClick(view_0), url: view_0.url, name: view_0.name }, `navigation_${index}`))
23986
+ Object.values(navigationEntries).filter((e_0) => e_0.group === group_0).map((view_0) => /* @__PURE__ */ jsx(DrawerNavigationItem, { icon: /* @__PURE__ */ jsx(IconForView, { collectionOrView: view_0.collection ?? view_0.view, size: "small" }), tooltipsOpen, adminMenuOpen, drawerOpen, onClick: () => onClick(view_0), url: view_0.url, name: view_0.name }, view_0.id))
23057
23987
  ] }, `drawer_group_${group_0}`);
23058
23988
  $[41] = adminMenuOpen;
23059
23989
  $[42] = buildGroupHeader;
@@ -23107,13 +24037,13 @@ function DefaultDrawer(t0) {
23107
24037
  adminViews.length > 0 && /* @__PURE__ */ jsx(Menu, { side: "right", open: adminMenuOpen, onOpenChange: setAdminMenuOpen, trigger: /* @__PURE__ */ jsxs(IconButton, { shape: "square", className: "m-4 text-surface-900 dark:text-white w-fit", children: [
23108
24038
  /* @__PURE__ */ jsx(Tooltip, { title: "Admin", open: tooltipsOpen, side: "right", sideOffset: 28, children: /* @__PURE__ */ jsx(MoreVertIcon, {}) }),
23109
24039
  drawerOpen && /* @__PURE__ */ jsx("div", { className: cls(drawerOpen ? "opacity-100" : "opacity-0 hidden", "mx-4 font-inherit text-inherit"), children: "ADMIN" })
23110
- ] }), children: adminViews.map((entry, index_0) => /* @__PURE__ */ jsxs(MenuItem, { onClick: (event) => {
24040
+ ] }), children: adminViews.map((entry) => /* @__PURE__ */ jsxs(MenuItem, { onClick: (event) => {
23111
24041
  event.preventDefault();
23112
- navigate(entry.path);
24042
+ navigate(entry.url);
23113
24043
  }, children: [
23114
24044
  /* @__PURE__ */ jsx(IconForView, { collectionOrView: entry.view }),
23115
24045
  entry.name
23116
- ] }, `navigation_${index_0}`)) })
24046
+ ] }, entry.id)) })
23117
24047
  ] }) });
23118
24048
  $[0] = adminMenuOpen;
23119
24049
  $[1] = analyticsController;
@@ -23366,10 +24296,21 @@ const DEFAULT_FIELD_CONFIGS = {
23366
24296
  Field: StorageUploadFieldBinding
23367
24297
  }
23368
24298
  },
24299
+ reference_as_string: {
24300
+ key: "reference_as_string",
24301
+ name: "Reference (as string)",
24302
+ description: "The value refers to a different collection (it is saved as a string)",
24303
+ Icon: LinkIcon,
24304
+ color: "#154fb3",
24305
+ property: {
24306
+ dataType: "string",
24307
+ Field: ReferenceAsStringFieldBinding
24308
+ }
24309
+ },
23369
24310
  reference: {
23370
24311
  key: "reference",
23371
24312
  name: "Reference",
23372
- description: "The value refers to a different collection",
24313
+ description: "The value refers to a different collection (it is saved as a reference)",
23373
24314
  Icon: LinkIcon,
23374
24315
  color: "#ff0042",
23375
24316
  property: {
@@ -23500,6 +24441,8 @@ function getDefaultFieldId(property) {
23500
24441
  return "email";
23501
24442
  } else if (property.enumValues) {
23502
24443
  return "select";
24444
+ } else if (property.reference) {
24445
+ return "reference_as_string";
23503
24446
  } else {
23504
24447
  return "text_field";
23505
24448
  }
@@ -24431,6 +25374,7 @@ function _temp3(child_1) {
24431
25374
  return child_1.type.componentType !== "Drawer" && child_1.type.componentType !== "AppBar";
24432
25375
  }
24433
25376
  export {
25377
+ ADMIN_GROUP_NAME,
24434
25378
  AppBar,
24435
25379
  AppContext,
24436
25380
  ArrayContainer,
@@ -24455,6 +25399,7 @@ export {
24455
25399
  CircularProgressCenter,
24456
25400
  ConfirmationDialog,
24457
25401
  DEFAULT_FIELD_CONFIGS,
25402
+ DEFAULT_GROUP_NAME,
24458
25403
  DRAWER_WIDTH,
24459
25404
  DatePreview,
24460
25405
  DateTimeFieldBinding,
@@ -24497,6 +25442,8 @@ export {
24497
25442
  ModeControllerContext,
24498
25443
  ModeControllerProvider,
24499
25444
  MultiSelectFieldBinding,
25445
+ NAVIGATION_ADMIN_GROUP_NAME,
25446
+ NAVIGATION_DEFAULT_GROUP_NAME,
24500
25447
  NavigationCard,
24501
25448
  NavigationCardBinding,
24502
25449
  NavigationGroup,
@@ -24510,6 +25457,7 @@ export {
24510
25457
  PropertyPreview,
24511
25458
  PropertyTableCell,
24512
25459
  ReadOnlyFieldBinding,
25460
+ ReferenceAsStringFieldBinding,
24513
25461
  ReferenceFieldBinding,
24514
25462
  ReferencePreview,
24515
25463
  ReferenceSelectionTable,