@plumile/backoffice-react 0.1.201 → 0.1.205

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 (167) hide show
  1. package/README.md +4 -4
  2. package/lib/esm/auth/login/LoginFlow.js.map +1 -1
  3. package/lib/esm/auth/pages/AcceptInvitationScreen.js.map +1 -1
  4. package/lib/esm/auth/pages/PasswordResetCompleteScreen.js.map +1 -1
  5. package/lib/esm/auth/pages/PasswordResetRequestScreen.js.map +1 -1
  6. package/lib/esm/components/backoffice/detail/BackofficeEntitySummaryHeader.js +28 -28
  7. package/lib/esm/components/backoffice/detail/BackofficeEntitySummaryHeader.js.map +1 -1
  8. package/lib/esm/components/backoffice/scaffolds/BackofficeEntityListScaffold.js +183 -183
  9. package/lib/esm/components/backoffice/scaffolds/BackofficeEntityListScaffold.js.map +1 -1
  10. package/lib/esm/hooks/useAuth.js +56 -56
  11. package/lib/esm/hooks/useAuth.js.map +1 -1
  12. package/lib/esm/hooks/useConditionalSubscription.js +18 -18
  13. package/lib/esm/hooks/useConditionalSubscription.js.map +1 -1
  14. package/lib/esm/index.js +49 -57
  15. package/lib/esm/pages/BackofficeEntityDetailPage.js +97 -97
  16. package/lib/esm/pages/BackofficeEntityDetailPage.js.map +1 -1
  17. package/lib/esm/pages/BackofficeLayoutPage.js +19 -19
  18. package/lib/esm/pages/BackofficeLayoutPage.js.map +1 -1
  19. package/lib/esm/provider/BackofficeProvider.js +33 -33
  20. package/lib/esm/router/createBackofficeRoutes.js +26 -28
  21. package/lib/esm/router/createBackofficeRoutes.js.map +1 -1
  22. package/lib/esm/storybook/relay/RelayStory.js +32 -32
  23. package/lib/esm/storybook/relay/RelayStory.js.map +1 -1
  24. package/lib/esm/storybook/relay/mockResolvers.js.map +1 -1
  25. package/lib/esm/style.css +1 -1
  26. package/lib/types/components/backoffice/detail/BackofficeEntitySummaryHeader.d.ts +1 -1
  27. package/lib/types/components/backoffice/detail/BackofficeEntitySummaryHeader.d.ts.map +1 -1
  28. package/lib/types/hooks/useAuth.d.ts.map +1 -1
  29. package/lib/types/hooks/useConditionalSubscription.d.ts.map +1 -1
  30. package/lib/types/i18n/locales/en/backofficeReact.d.ts +5 -0
  31. package/lib/types/i18n/locales/fr/backofficeReact.d.ts +5 -0
  32. package/lib/types/index.d.ts +1 -9
  33. package/lib/types/index.d.ts.map +1 -1
  34. package/lib/types/pages/BackofficeLayoutPage.d.ts.map +1 -1
  35. package/lib/types/router/createBackofficeRoutes.d.ts +3 -3
  36. package/lib/types/router/createBackofficeRoutes.d.ts.map +1 -1
  37. package/lib/types/storybook/relay/RelayStory.d.ts +1 -1
  38. package/lib/types/storybook/relay/RelayStory.d.ts.map +1 -1
  39. package/lib/types/storybook/relay/mockResolvers.d.ts +9 -1
  40. package/lib/types/storybook/relay/mockResolvers.d.ts.map +1 -1
  41. package/package.json +12 -15
  42. package/lib/esm/_virtual/_rolldown/runtime.js +0 -7
  43. package/lib/esm/components/backoffice/detail/BackofficeDetailFlagTag.js +0 -13
  44. package/lib/esm/components/backoffice/detail/BackofficeDetailFlagTag.js.map +0 -1
  45. package/lib/esm/components/backoffice/detail/BackofficeDetailTaggedValue.js +0 -12
  46. package/lib/esm/components/backoffice/detail/BackofficeDetailTaggedValue.js.map +0 -1
  47. package/lib/esm/components/backoffice/detail/BackofficeEnumLabel.js +0 -16
  48. package/lib/esm/components/backoffice/detail/BackofficeEnumLabel.js.map +0 -1
  49. package/lib/esm/components/backoffice/detail/BackofficeReferenceValue.js +0 -17
  50. package/lib/esm/components/backoffice/detail/BackofficeReferenceValue.js.map +0 -1
  51. package/lib/esm/components/backoffice/detail/BackofficeStatusGroup.js +0 -8
  52. package/lib/esm/components/backoffice/detail/BackofficeStatusGroup.js.map +0 -1
  53. package/lib/esm/components/backoffice/detail/BackofficeStatusMetaBadge.js +0 -16
  54. package/lib/esm/components/backoffice/detail/BackofficeStatusMetaBadge.js.map +0 -1
  55. package/lib/esm/components/backoffice/detail/backofficeDetailRelationLink.css.js +0 -6
  56. package/lib/esm/components/backoffice/detail/backofficeDetailRelationLink.css.js.map +0 -1
  57. package/lib/esm/components/backoffice/refs/backofficeEntityIdRef.css.js +0 -6
  58. package/lib/esm/components/backoffice/refs/backofficeEntityIdRef.css.js.map +0 -1
  59. package/lib/esm/components/backoffice/routing/BackofficeRoutePendingBar.js +0 -12
  60. package/lib/esm/components/backoffice/routing/BackofficeRoutePendingBar.js.map +0 -1
  61. package/lib/esm/components/backoffice/routing/backofficeRoutePendingBar.css.js +0 -7
  62. package/lib/esm/components/backoffice/routing/backofficeRoutePendingBar.css.js.map +0 -1
  63. package/lib/esm/modules/base64.js +0 -21
  64. package/lib/esm/modules/base64.js.map +0 -1
  65. package/lib/esm/node_modules/@babel/runtime/helpers/arrayLikeToArray.js +0 -15
  66. package/lib/esm/node_modules/@babel/runtime/helpers/arrayLikeToArray.js.map +0 -1
  67. package/lib/esm/node_modules/@babel/runtime/helpers/arrayWithoutHoles.js +0 -15
  68. package/lib/esm/node_modules/@babel/runtime/helpers/arrayWithoutHoles.js.map +0 -1
  69. package/lib/esm/node_modules/@babel/runtime/helpers/defineProperty.js +0 -20
  70. package/lib/esm/node_modules/@babel/runtime/helpers/defineProperty.js.map +0 -1
  71. package/lib/esm/node_modules/@babel/runtime/helpers/interopRequireDefault.js +0 -13
  72. package/lib/esm/node_modules/@babel/runtime/helpers/interopRequireDefault.js.map +0 -1
  73. package/lib/esm/node_modules/@babel/runtime/helpers/iterableToArray.js +0 -13
  74. package/lib/esm/node_modules/@babel/runtime/helpers/iterableToArray.js.map +0 -1
  75. package/lib/esm/node_modules/@babel/runtime/helpers/nonIterableSpread.js +0 -13
  76. package/lib/esm/node_modules/@babel/runtime/helpers/nonIterableSpread.js.map +0 -1
  77. package/lib/esm/node_modules/@babel/runtime/helpers/objectSpread2.js +0 -33
  78. package/lib/esm/node_modules/@babel/runtime/helpers/objectSpread2.js.map +0 -1
  79. package/lib/esm/node_modules/@babel/runtime/helpers/objectWithoutPropertiesLoose.js +0 -19
  80. package/lib/esm/node_modules/@babel/runtime/helpers/objectWithoutPropertiesLoose.js.map +0 -1
  81. package/lib/esm/node_modules/@babel/runtime/helpers/toConsumableArray.js +0 -18
  82. package/lib/esm/node_modules/@babel/runtime/helpers/toConsumableArray.js.map +0 -1
  83. package/lib/esm/node_modules/@babel/runtime/helpers/toPrimitive.js +0 -22
  84. package/lib/esm/node_modules/@babel/runtime/helpers/toPrimitive.js.map +0 -1
  85. package/lib/esm/node_modules/@babel/runtime/helpers/toPropertyKey.js +0 -17
  86. package/lib/esm/node_modules/@babel/runtime/helpers/toPropertyKey.js.map +0 -1
  87. package/lib/esm/node_modules/@babel/runtime/helpers/typeof.js +0 -18
  88. package/lib/esm/node_modules/@babel/runtime/helpers/typeof.js.map +0 -1
  89. package/lib/esm/node_modules/@babel/runtime/helpers/unsupportedIterableToArray.js +0 -19
  90. package/lib/esm/node_modules/@babel/runtime/helpers/unsupportedIterableToArray.js.map +0 -1
  91. package/lib/esm/node_modules/fbjs/lib/areEqual.js +0 -42
  92. package/lib/esm/node_modules/fbjs/lib/areEqual.js.map +0 -1
  93. package/lib/esm/node_modules/invariant/browser.js +0 -30
  94. package/lib/esm/node_modules/invariant/browser.js.map +0 -1
  95. package/lib/esm/node_modules/relay-test-utils/index.js +0 -11
  96. package/lib/esm/node_modules/relay-test-utils/index.js.map +0 -1
  97. package/lib/esm/node_modules/relay-test-utils/lib/RelayMockPayloadGenerator.js +0 -288
  98. package/lib/esm/node_modules/relay-test-utils/lib/RelayMockPayloadGenerator.js.map +0 -1
  99. package/lib/esm/node_modules/relay-test-utils/lib/RelayModernMockEnvironment.js +0 -183
  100. package/lib/esm/node_modules/relay-test-utils/lib/RelayModernMockEnvironment.js.map +0 -1
  101. package/lib/esm/node_modules/relay-test-utils/lib/RelayResolverTestUtils.js +0 -19
  102. package/lib/esm/node_modules/relay-test-utils/lib/RelayResolverTestUtils.js.map +0 -1
  103. package/lib/esm/node_modules/relay-test-utils/lib/index.js +0 -21
  104. package/lib/esm/node_modules/relay-test-utils/lib/index.js.map +0 -1
  105. package/lib/esm/node_modules/relay-test-utils/lib/unwrapContainer.js +0 -16
  106. package/lib/esm/node_modules/relay-test-utils/lib/unwrapContainer.js.map +0 -1
  107. package/lib/esm/relay/RelayProvider.js +0 -2
  108. package/lib/esm/relay/envHelpers.js +0 -63
  109. package/lib/esm/relay/envHelpers.js.map +0 -1
  110. package/lib/esm/relay/environment.js +0 -2
  111. package/lib/esm/relay/shortAccessTokenEnvironment.js +0 -2
  112. package/lib/esm/relay/useRelayOperationActivity.js +0 -2
  113. package/lib/esm/storybook/relay/relay-test-utils.d.js +0 -0
  114. package/lib/types/auth/AuthFlows.stories.d.ts +0 -19
  115. package/lib/types/auth/AuthFlows.stories.d.ts.map +0 -1
  116. package/lib/types/components/backoffice/billing/BackofficeBillingUsageChart.stories.d.ts +0 -41
  117. package/lib/types/components/backoffice/billing/BackofficeBillingUsageChart.stories.d.ts.map +0 -1
  118. package/lib/types/components/backoffice/detail/BackofficeDetailFlagTag.d.ts +0 -11
  119. package/lib/types/components/backoffice/detail/BackofficeDetailFlagTag.d.ts.map +0 -1
  120. package/lib/types/components/backoffice/detail/BackofficeDetailPrimitives.stories.d.ts +0 -17
  121. package/lib/types/components/backoffice/detail/BackofficeDetailPrimitives.stories.d.ts.map +0 -1
  122. package/lib/types/components/backoffice/detail/BackofficeDetailTaggedValue.d.ts +0 -13
  123. package/lib/types/components/backoffice/detail/BackofficeDetailTaggedValue.d.ts.map +0 -1
  124. package/lib/types/components/backoffice/detail/BackofficeEnumLabel.d.ts +0 -9
  125. package/lib/types/components/backoffice/detail/BackofficeEnumLabel.d.ts.map +0 -1
  126. package/lib/types/components/backoffice/detail/BackofficeReferenceValue.d.ts +0 -10
  127. package/lib/types/components/backoffice/detail/BackofficeReferenceValue.d.ts.map +0 -1
  128. package/lib/types/components/backoffice/detail/BackofficeStatusGroup.d.ts +0 -8
  129. package/lib/types/components/backoffice/detail/BackofficeStatusGroup.d.ts.map +0 -1
  130. package/lib/types/components/backoffice/detail/BackofficeStatusMetaBadge.d.ts +0 -11
  131. package/lib/types/components/backoffice/detail/BackofficeStatusMetaBadge.d.ts.map +0 -1
  132. package/lib/types/components/backoffice/detail/backofficeDetailRelationLink.css.d.ts +0 -6
  133. package/lib/types/components/backoffice/detail/backofficeDetailRelationLink.css.d.ts.map +0 -1
  134. package/lib/types/components/backoffice/errors/BackofficeErrorBoundary.stories.d.ts +0 -12
  135. package/lib/types/components/backoffice/errors/BackofficeErrorBoundary.stories.d.ts.map +0 -1
  136. package/lib/types/components/backoffice/filters/EntityIdFilterField.stories.d.ts +0 -12
  137. package/lib/types/components/backoffice/filters/EntityIdFilterField.stories.d.ts.map +0 -1
  138. package/lib/types/components/backoffice/hub/BackofficeHubTemplate.stories.d.ts +0 -49
  139. package/lib/types/components/backoffice/hub/BackofficeHubTemplate.stories.d.ts.map +0 -1
  140. package/lib/types/components/backoffice/overview/BackofficeOverviewLayout.stories.d.ts +0 -11
  141. package/lib/types/components/backoffice/overview/BackofficeOverviewLayout.stories.d.ts.map +0 -1
  142. package/lib/types/components/backoffice/pickers/EntityIdPickerDialog.stories.d.ts +0 -12
  143. package/lib/types/components/backoffice/pickers/EntityIdPickerDialog.stories.d.ts.map +0 -1
  144. package/lib/types/components/backoffice/refs/backofficeEntityIdRef.css.d.ts +0 -2
  145. package/lib/types/components/backoffice/refs/backofficeEntityIdRef.css.d.ts.map +0 -1
  146. package/lib/types/components/backoffice/routing/BackofficeRoutePendingBar.d.ts +0 -4
  147. package/lib/types/components/backoffice/routing/BackofficeRoutePendingBar.d.ts.map +0 -1
  148. package/lib/types/components/backoffice/routing/backofficeRoutePendingBar.css.d.ts +0 -3
  149. package/lib/types/components/backoffice/routing/backofficeRoutePendingBar.css.d.ts.map +0 -1
  150. package/lib/types/components/backoffice/scaffolds/BackofficeTabbedDetailShell.stories.d.ts +0 -11
  151. package/lib/types/components/backoffice/scaffolds/BackofficeTabbedDetailShell.stories.d.ts.map +0 -1
  152. package/lib/types/components/backoffice/tools/BackofficeTools.stories.d.ts +0 -17
  153. package/lib/types/components/backoffice/tools/BackofficeTools.stories.d.ts.map +0 -1
  154. package/lib/types/modules/base64.d.ts +0 -3
  155. package/lib/types/modules/base64.d.ts.map +0 -1
  156. package/lib/types/pages/BackofficeDashboardPage.stories.d.ts +0 -9
  157. package/lib/types/pages/BackofficeDashboardPage.stories.d.ts.map +0 -1
  158. package/lib/types/relay/RelayProvider.d.ts +0 -2
  159. package/lib/types/relay/RelayProvider.d.ts.map +0 -1
  160. package/lib/types/relay/envHelpers.d.ts +0 -25
  161. package/lib/types/relay/envHelpers.d.ts.map +0 -1
  162. package/lib/types/relay/environment.d.ts +0 -2
  163. package/lib/types/relay/environment.d.ts.map +0 -1
  164. package/lib/types/relay/shortAccessTokenEnvironment.d.ts +0 -5
  165. package/lib/types/relay/shortAccessTokenEnvironment.d.ts.map +0 -1
  166. package/lib/types/relay/useRelayOperationActivity.d.ts +0 -2
  167. package/lib/types/relay/useRelayOperationActivity.d.ts.map +0 -1
@@ -7,18 +7,18 @@ import { BackofficePermissionsProvider as o } from "../components/backoffice/lay
7
7
  import { buildSidebarSections as s } from "../components/backoffice/layout/buildSidebarSections.js";
8
8
  import te from "../components/backoffice/layout/mapViewerToSidebarProfileView.js";
9
9
  import { BackofficeContentBoundary as ne } from "../components/backoffice/routing/BackofficeContentBoundary.js";
10
- import { resetRelayStore as re } from "../relay/environment.js";
11
- import { useRelayEnvironment as ie } from "../relay/useRelayEnvironment.js";
12
- import ae from "../hooks/useBackofficeSidebarPins.js";
13
- import oe from "../hooks/useSidebarGroupCollapse.js";
14
- import { useCallback as se, useContext as ce, useEffect as c, useMemo as l, useState as u } from "react";
10
+ import { useRelayEnvironment as re } from "../relay/useRelayEnvironment.js";
11
+ import ie from "../hooks/useBackofficeSidebarPins.js";
12
+ import ae from "../hooks/useSidebarGroupCollapse.js";
13
+ import { useCallback as oe, useContext as se, useEffect as c, useMemo as l, useState as u } from "react";
15
14
  import { jsx as d } from "react/jsx-runtime";
16
- import { useTranslation as le } from "react-i18next";
17
- import { commitMutation as ue, usePreloadedQuery as f } from "react-relay";
18
- import { ToastProvider as de } from "@plumile/ui/atomic/molecules/toast/ToastProvider.js";
19
- import fe from "@plumile/router/routing/RoutingContext.js";
20
- import { GlobalSearchInput as pe } from "@plumile/ui/backoffice/molecules/global_search_input/GlobalSearchInput.js";
21
- import me from "@plumile/router/routing/useLocation.js";
15
+ import { useTranslation as ce } from "react-i18next";
16
+ import { commitMutation as le, usePreloadedQuery as f } from "react-relay";
17
+ import { ToastProvider as ue } from "@plumile/ui/atomic/molecules/toast/ToastProvider.js";
18
+ import de from "@plumile/router/routing/RoutingContext.js";
19
+ import { GlobalSearchInput as fe } from "@plumile/ui/backoffice/molecules/global_search_input/GlobalSearchInput.js";
20
+ import pe from "@plumile/router/routing/useLocation.js";
21
+ import { resetRelayStore as me } from "@plumile/relay/environment.js";
22
22
  import { AdminShellLayout as he } from "@plumile/ui/admin/templates/admin_shell_layout/AdminShellLayout.js";
23
23
  import { SidebarProfileMenu as p } from "@plumile/ui/components/navigation/sidebar/SidebarProfileMenu.js";
24
24
  //#region src/pages/BackofficeLayoutPage.tsx
@@ -41,7 +41,7 @@ var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", v
41
41
  window.localStorage.setItem(e, JSON.stringify(t));
42
42
  } catch {}
43
43
  }, m = ({ children: f, permissions: m, authStatus: h, activeGroupId: g }) => {
44
- let { t: _ } = le(), { t: v } = t(), { pathname: y } = me(), b = ce(fe), x = ie(), { auth: S, basePath: C, dashboards: w, entities: T, sidebar: E } = n(), [D, be] = u(""), O = E?.preferences?.storageKey ?? _e, k = E?.preferences?.persistCollapsed === !0, [A, xe] = u(() => {
44
+ let { t: _ } = ce(), { t: v } = t(), { pathname: y } = pe(), b = se(de), x = re(), { auth: S, basePath: C, dashboards: w, entities: T, sidebar: E } = n(), [D, be] = u(""), O = E?.preferences?.storageKey ?? _e, k = E?.preferences?.persistCollapsed === !0, [A, xe] = u(() => {
45
45
  if (!k || typeof window > "u") return !1;
46
46
  try {
47
47
  return window.localStorage.getItem(`${O}:collapsed`) === "true";
@@ -89,7 +89,7 @@ var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", v
89
89
  L,
90
90
  _
91
91
  ]);
92
- let H = E?.pinnedItems?.enabled === !0, { pins: Ee, toggle: De, reorder: Oe } = ae({
92
+ let H = E?.pinnedItems?.enabled === !0, { pins: Ee, toggle: De, reorder: Oe } = ie({
93
93
  enabled: H,
94
94
  storageKey: E?.pinnedItems?.storageKey,
95
95
  visibleEntityIds: Te
@@ -97,7 +97,7 @@ var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", v
97
97
  H && (U = Ee, W = De, G = Oe);
98
98
  let K;
99
99
  E?.preferences?.storageKey != null && (K = `${E.preferences.storageKey}:groups`);
100
- let { collapsedByGroupId: q, setCollapsed: J } = oe({
100
+ let { collapsedByGroupId: q, setCollapsed: J } = ae({
101
101
  groupIds: Ce,
102
102
  activeGroupId: g,
103
103
  defaultCollapsedByGroupId: we,
@@ -169,12 +169,12 @@ var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", v
169
169
  W,
170
170
  v,
171
171
  _
172
- ]), Y = se(() => {
172
+ ]), Y = oe(() => {
173
173
  j || (M(!0), (async () => {
174
174
  try {
175
175
  let t = await S.logout.load();
176
176
  await new Promise((e, n) => {
177
- ue(x, {
177
+ le(x, {
178
178
  mutation: t.logoutMutation,
179
179
  variables: {},
180
180
  onCompleted: () => {
@@ -184,7 +184,7 @@ var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", v
184
184
  n(e);
185
185
  }
186
186
  });
187
- }), localStorage.removeItem("auth_token"), localStorage.removeItem("remember_me"), re(), b?.history.push({ pathname: e(C) });
187
+ }), localStorage.removeItem("auth_token"), localStorage.removeItem("remember_me"), me(), b?.history.push({ pathname: e(C) });
188
188
  } finally {
189
189
  M(!1);
190
190
  }
@@ -220,13 +220,13 @@ var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", v
220
220
  isSigningOut: j
221
221
  }), Q = null;
222
222
  N != null && (Q = /* @__PURE__ */ d(ne, { children: f }));
223
- let $ = /* @__PURE__ */ d(pe, {
223
+ let $ = /* @__PURE__ */ d(fe, {
224
224
  value: D,
225
225
  onChange: be,
226
226
  placeholder: v("sidebar.search.placeholder"),
227
227
  ariaLabel: v("sidebar.search.placeholder")
228
228
  });
229
- return /* @__PURE__ */ d(de, { children: /* @__PURE__ */ d(he, {
229
+ return /* @__PURE__ */ d(ue, { children: /* @__PURE__ */ d(he, {
230
230
  sidebar: {
231
231
  sections: ke,
232
232
  search: $,
@@ -1 +1 @@
1
- {"version":3,"file":"BackofficeLayoutPage.js","names":[],"sources":["../../../src/pages/BackofficeLayoutPage.tsx"],"sourcesContent":["import {\n useEffect,\n useMemo,\n type JSX,\n type ReactNode,\n useCallback,\n useContext,\n useState,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n commitMutation,\n usePreloadedQuery,\n type PreloadedQuery,\n} from 'react-relay';\nimport type {\n GraphQLTaggedNode,\n MutationParameters,\n OperationType,\n} from 'relay-runtime';\nimport RoutingContext from '@plumile/router/routing/RoutingContext.js';\nimport useLocation from '@plumile/router/routing/useLocation.js';\n\nimport { AdminShellLayout } from '@plumile/ui/admin/templates/admin_shell_layout/AdminShellLayout.js';\nimport { ToastProvider } from '@plumile/ui/atomic/molecules/toast/ToastProvider.js';\nimport { GlobalSearchInput } from '@plumile/ui/backoffice/molecules/global_search_input/GlobalSearchInput.js';\nimport { SidebarProfileMenu } from '@plumile/ui/components/navigation/sidebar/SidebarProfileMenu.js';\n\nimport { useBackofficeReactTranslation } from '../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeConfig } from '../provider/BackofficeConfigContext.js';\nimport type { LogoutResponse, LogoutVariables } from '../hooks/useAuth.js';\nimport { useBackofficeSidebarPins } from '../hooks/useBackofficeSidebarPins.js';\nimport { useSidebarGroupCollapse } from '../hooks/useSidebarGroupCollapse.js';\nimport { buildSidebarSections } from '../components/backoffice/layout/buildSidebarSections.js';\nimport { BackofficeContentBoundary } from '../components/backoffice/routing/BackofficeContentBoundary.js';\nimport {\n resolveActiveEntityId,\n resolveSidebarGroups,\n resolveVisibleEntityIds,\n} from '../components/backoffice/layout/sidebarUtils.js';\nimport { BackofficeTopbarPortalContextProvider } from '../components/backoffice/layout/breadcrumb/BackofficeTopbarPortalContext.js';\nimport { BackofficePermissionsProvider } from '../components/backoffice/layout/BackofficePermissionsContext.js';\nimport {\n mapViewerToSidebarProfileView,\n type BackofficeViewerIdentity,\n} from '../components/backoffice/layout/mapViewerToSidebarProfileView.js';\nimport { resetRelayStore } from '../relay/environment.js';\nimport { useRelayEnvironment } from '../relay/useRelayEnvironment.js';\nimport { getBackofficeLoginPath } from '../router/backofficeAuthPaths.js';\nimport type { BackofficeSidebarRecentItem } from '../provider/types.js';\n\nexport type BackofficeLayoutPageProps = {\n children: ReactNode;\n permissionsQuery?: GraphQLTaggedNode;\n prepared?: PreloadedQuery<OperationType> | null;\n authStatus?: {\n isLoggedIn?: boolean | null;\n me?: BackofficeViewerIdentity | null;\n } | null;\n activeGroupId?: string | null;\n};\n\ntype LayoutShellProps = {\n children: ReactNode;\n permissions: unknown;\n authStatus?: {\n isLoggedIn?: boolean | null;\n me?: BackofficeViewerIdentity | null;\n } | null;\n activeGroupId?: string | null;\n};\n\nconst DEFAULT_RECENT_ITEMS_STORAGE_KEY = 'plumile:backoffice:recent-items';\nconst DEFAULT_SIDEBAR_PREFS_STORAGE_KEY = 'plumile:backoffice:sidebar';\n\nconst readRecentItems = (\n storageKey: string,\n): readonly BackofficeSidebarRecentItem[] => {\n if (typeof window === 'undefined') {\n return [];\n }\n try {\n const raw = window.localStorage.getItem(storageKey);\n if (raw == null) {\n return [];\n }\n const parsed = JSON.parse(raw) as unknown;\n if (!Array.isArray(parsed)) {\n return [];\n }\n return parsed.filter((item): item is BackofficeSidebarRecentItem => {\n if (item == null || typeof item !== 'object') {\n return false;\n }\n const candidate = item as Partial<BackofficeSidebarRecentItem>;\n return (\n (candidate.kind === 'entity' || candidate.kind === 'tool') &&\n typeof candidate.id === 'string' &&\n typeof candidate.label === 'string' &&\n typeof candidate.href === 'string' &&\n typeof candidate.visitedAt === 'number'\n );\n });\n } catch {\n return [];\n }\n};\n\nconst writeRecentItems = (\n storageKey: string,\n items: readonly BackofficeSidebarRecentItem[],\n): void => {\n if (typeof window === 'undefined') {\n return;\n }\n try {\n window.localStorage.setItem(storageKey, JSON.stringify(items));\n } catch {\n // Ignore storage quota / privacy mode failures.\n }\n};\n\nconst BackofficeLayoutShell = ({\n children,\n permissions,\n authStatus,\n activeGroupId,\n}: LayoutShellProps): JSX.Element => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const { pathname } = useLocation();\n const routing = useContext(RoutingContext);\n const relayEnvironment = useRelayEnvironment();\n const {\n auth: authConfig,\n basePath,\n dashboards,\n entities,\n sidebar,\n } = useBackofficeConfig();\n const [sidebarQuery, setSidebarQuery] = useState('');\n const sidebarPreferencesStorageKey =\n sidebar?.preferences?.storageKey ?? DEFAULT_SIDEBAR_PREFS_STORAGE_KEY;\n const persistSidebarCollapsed =\n sidebar?.preferences?.persistCollapsed === true;\n const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(() => {\n if (!persistSidebarCollapsed || typeof window === 'undefined') {\n return false;\n }\n try {\n return (\n window.localStorage.getItem(\n `${sidebarPreferencesStorageKey}:collapsed`,\n ) === 'true'\n );\n } catch {\n return false;\n }\n });\n const [isSigningOut, setIsSigningOut] = useState(false);\n const [topbarTarget, setTopbarTarget] = useState<HTMLDivElement | null>(null);\n const recentItemsConfig = sidebar?.recentItems;\n const recentItemsEnabled = recentItemsConfig?.enabled === true;\n const recentItemsStorageKey =\n recentItemsConfig?.storageKey ?? DEFAULT_RECENT_ITEMS_STORAGE_KEY;\n const recentItemsMaxItems = recentItemsConfig?.maxItems ?? 8;\n const [recentItems, setRecentItems] = useState<\n readonly BackofficeSidebarRecentItem[]\n >(() => {\n if (!recentItemsEnabled) {\n return [];\n }\n return readRecentItems(recentItemsStorageKey);\n });\n\n useEffect(() => {\n if (!persistSidebarCollapsed || typeof window === 'undefined') {\n return;\n }\n try {\n window.localStorage.setItem(\n `${sidebarPreferencesStorageKey}:collapsed`,\n String(isSidebarCollapsed),\n );\n } catch {\n // Ignore storage quota / privacy mode failures.\n }\n }, [\n isSidebarCollapsed,\n persistSidebarCollapsed,\n sidebarPreferencesStorageKey,\n ]);\n\n const groups = useMemo(() => {\n return resolveSidebarGroups(entities, sidebar);\n }, [entities, sidebar]);\n\n const groupIds = useMemo(() => {\n return Object.keys(groups);\n }, [groups]);\n\n const defaultCollapsedByGroupId = useMemo(() => {\n return Object.fromEntries(\n Object.entries(groups).map(([groupId, group]) => {\n return [groupId, group.behavior?.defaultCollapsed ?? true];\n }),\n );\n }, [groups]);\n\n const visibleEntityIds = useMemo(() => {\n return resolveVisibleEntityIds(groups, entities, sidebar, permissions);\n }, [entities, groups, permissions, sidebar]);\n\n const activeEntityId = useMemo(() => {\n return resolveActiveEntityId(pathname, entities);\n }, [entities, pathname]);\n\n useEffect(() => {\n if (!recentItemsEnabled || activeEntityId == null) {\n return;\n }\n const config = entities[activeEntityId];\n if (config == null) {\n return;\n }\n if (config.kind !== 'tool' && !config.hasList) {\n return;\n }\n const href = config.routes.list;\n let kind: BackofficeSidebarRecentItem['kind'] = 'entity';\n if (config.kind === 'tool') {\n kind = 'tool';\n }\n const item: BackofficeSidebarRecentItem = {\n kind,\n id: activeEntityId,\n label: config.label(tApp),\n href,\n visitedAt: Date.now(),\n };\n setRecentItems((prev) => {\n const next = [\n item,\n ...prev.filter((entry) => {\n return entry.id !== item.id || entry.kind !== item.kind;\n }),\n ].slice(0, recentItemsMaxItems);\n writeRecentItems(recentItemsStorageKey, next);\n return next;\n });\n }, [\n activeEntityId,\n entities,\n recentItemsEnabled,\n recentItemsMaxItems,\n recentItemsStorageKey,\n tApp,\n ]);\n\n const pinningEnabled = sidebar?.pinnedItems?.enabled === true;\n\n const {\n pins,\n toggle: togglePin,\n reorder: reorderPin,\n } = useBackofficeSidebarPins({\n enabled: pinningEnabled,\n storageKey: sidebar?.pinnedItems?.storageKey,\n visibleEntityIds,\n });\n\n let sidebarPinnedEntityIds: readonly string[] | undefined;\n let sidebarTogglePin: ((entityId: string) => void) | undefined;\n let sidebarReorderPin: ((fromId: string, toId: string) => void) | undefined;\n if (pinningEnabled) {\n sidebarPinnedEntityIds = pins;\n sidebarTogglePin = togglePin;\n sidebarReorderPin = reorderPin;\n }\n\n let groupCollapseStorageKey: string | undefined;\n if (sidebar?.preferences?.storageKey != null) {\n groupCollapseStorageKey = `${sidebar.preferences.storageKey}:groups`;\n }\n\n const { collapsedByGroupId, setCollapsed } = useSidebarGroupCollapse({\n groupIds,\n activeGroupId,\n defaultCollapsedByGroupId,\n persist: sidebar?.preferences?.persistGroups === true,\n storageKey: groupCollapseStorageKey,\n });\n\n const sections = useMemo(() => {\n return buildSidebarSections({\n basePath,\n pathname,\n entities,\n dashboards,\n sidebar,\n permissions,\n searchQuery: sidebarQuery,\n tApp,\n t,\n pinnedEntityIds: sidebarPinnedEntityIds,\n recentItems,\n onTogglePin: sidebarTogglePin,\n onReorderPin: sidebarReorderPin,\n collapsedByGroupId,\n onGroupCollapsedChange: setCollapsed,\n sidebarCollapsed: false,\n });\n }, [\n basePath,\n collapsedByGroupId,\n entities,\n dashboards,\n pathname,\n permissions,\n recentItems,\n setCollapsed,\n sidebar,\n sidebarPinnedEntityIds,\n sidebarQuery,\n sidebarReorderPin,\n sidebarTogglePin,\n t,\n tApp,\n ]);\n\n const mobileSections = useMemo(() => {\n return buildSidebarSections({\n basePath,\n pathname,\n entities,\n dashboards,\n sidebar,\n permissions,\n searchQuery: sidebarQuery,\n tApp,\n t,\n pinnedEntityIds: sidebarPinnedEntityIds,\n recentItems,\n onTogglePin: sidebarTogglePin,\n onReorderPin: sidebarReorderPin,\n collapsedByGroupId,\n onGroupCollapsedChange: setCollapsed,\n sidebarCollapsed: false,\n });\n }, [\n basePath,\n collapsedByGroupId,\n entities,\n dashboards,\n pathname,\n permissions,\n recentItems,\n setCollapsed,\n sidebar,\n sidebarPinnedEntityIds,\n sidebarQuery,\n sidebarReorderPin,\n sidebarTogglePin,\n t,\n tApp,\n ]);\n\n const handleSignOut = useCallback(() => {\n if (isSigningOut) {\n return;\n }\n\n type LogoutMutation = MutationParameters & {\n response: LogoutResponse;\n variables: LogoutVariables;\n };\n\n setIsSigningOut(true);\n\n const runSignOut = async (): Promise<void> => {\n try {\n const config = await authConfig.logout.load();\n await new Promise<void>((resolve, reject) => {\n commitMutation<LogoutMutation>(relayEnvironment, {\n mutation: config.logoutMutation,\n variables: {},\n onCompleted: () => {\n resolve();\n },\n onError: (error) => {\n reject(error);\n },\n });\n });\n localStorage.removeItem('auth_token');\n localStorage.removeItem('remember_me');\n resetRelayStore();\n routing?.history.push({ pathname: getBackofficeLoginPath(basePath) });\n } finally {\n setIsSigningOut(false);\n }\n };\n\n runSignOut().catch(() => {\n /* noop */\n });\n }, [authConfig.logout, basePath, isSigningOut, relayEnvironment, routing]);\n\n const viewer = authStatus?.me ?? null;\n const sidebarProfile = useMemo(() => {\n return mapViewerToSidebarProfileView({\n viewer,\n unknownUserLabel: t('sidebar.profile.unknownUser'),\n });\n }, [t, viewer]);\n\n const sidebarFooter = (\n <SidebarProfileMenu\n collapsed={false}\n viewer={sidebarProfile}\n labels={{\n sectionTitle: t('sidebar.profile.title'),\n menuAriaLabel: t('sidebar.profile.menuAriaLabel'),\n signOut: t('sidebar.profile.actions.signOut'),\n }}\n onSignOut={handleSignOut}\n isSigningOut={isSigningOut}\n />\n );\n\n const mobileSidebarFooter = (\n <SidebarProfileMenu\n collapsed={false}\n viewer={sidebarProfile}\n labels={{\n sectionTitle: t('sidebar.profile.title'),\n menuAriaLabel: t('sidebar.profile.menuAriaLabel'),\n signOut: t('sidebar.profile.actions.signOut'),\n }}\n onSignOut={handleSignOut}\n isSigningOut={isSigningOut}\n />\n );\n\n let contentNode: JSX.Element | null = null;\n if (topbarTarget != null) {\n contentNode = (\n <BackofficeContentBoundary>{children}</BackofficeContentBoundary>\n );\n }\n\n const sidebarSearchNode = (\n <GlobalSearchInput\n value={sidebarQuery}\n onChange={setSidebarQuery}\n placeholder={t('sidebar.search.placeholder')}\n ariaLabel={t('sidebar.search.placeholder')}\n />\n );\n\n return (\n <ToastProvider>\n <AdminShellLayout\n sidebar={{\n sections,\n search: sidebarSearchNode,\n footer: sidebarFooter,\n isCollapsed: isSidebarCollapsed,\n onCollapsedChange: setIsSidebarCollapsed,\n collapseToggleLabel: t('sidebar.actions.collapseSidebar'),\n expandToggleLabel: t('sidebar.actions.expandSidebar'),\n navigationAriaLabel: t('sidebar.navigationAriaLabel'),\n }}\n mobileSidebar={{\n sections: mobileSections,\n search: sidebarSearchNode,\n footer: mobileSidebarFooter,\n isCollapsed: false,\n hideCollapseToggle: true,\n navigationAriaLabel: t('sidebar.navigationAriaLabel'),\n }}\n topbar={{\n breadcrumb: <div ref={setTopbarTarget} />,\n }}\n contentScrollMode=\"contained\"\n >\n <BackofficePermissionsProvider permissions={permissions}>\n <BackofficeTopbarPortalContextProvider\n value={{\n target: topbarTarget,\n dashboardHref: basePath,\n dashboardLabel: t('sidebar.items.dashboard'),\n }}\n >\n {contentNode}\n </BackofficeTopbarPortalContextProvider>\n </BackofficePermissionsProvider>\n </AdminShellLayout>\n </ToastProvider>\n );\n};\n\ntype LayoutWithPermissionsProps = {\n children: ReactNode;\n permissionsQuery: GraphQLTaggedNode;\n prepared: PreloadedQuery<OperationType>;\n authStatus?: {\n isLoggedIn?: boolean | null;\n me?: BackofficeViewerIdentity | null;\n } | null;\n activeGroupId?: string | null;\n};\n\nconst LayoutWithPermissions = ({\n children,\n permissionsQuery,\n prepared,\n authStatus,\n activeGroupId,\n}: LayoutWithPermissionsProps): JSX.Element => {\n const permissions = usePreloadedQuery(permissionsQuery, prepared);\n\n return (\n <BackofficeLayoutShell\n permissions={permissions}\n authStatus={authStatus}\n activeGroupId={activeGroupId}\n >\n {children}\n </BackofficeLayoutShell>\n );\n};\n\nexport const BackofficeLayoutPage = ({\n children,\n permissionsQuery,\n prepared,\n authStatus,\n activeGroupId,\n}: BackofficeLayoutPageProps): JSX.Element => {\n if (permissionsQuery != null && prepared != null) {\n return (\n <LayoutWithPermissions\n permissionsQuery={permissionsQuery}\n prepared={prepared}\n authStatus={authStatus}\n activeGroupId={activeGroupId}\n >\n {children}\n </LayoutWithPermissions>\n );\n }\n\n return (\n <BackofficeLayoutShell\n permissions={null}\n authStatus={authStatus}\n activeGroupId={activeGroupId}\n >\n {children}\n </BackofficeLayoutShell>\n );\n};\n\nexport default BackofficeLayoutPage;\n"],"mappings":"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"}
1
+ {"version":3,"file":"BackofficeLayoutPage.js","names":[],"sources":["../../../src/pages/BackofficeLayoutPage.tsx"],"sourcesContent":["import {\n useEffect,\n useMemo,\n type JSX,\n type ReactNode,\n useCallback,\n useContext,\n useState,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n commitMutation,\n usePreloadedQuery,\n type PreloadedQuery,\n} from 'react-relay';\nimport type {\n GraphQLTaggedNode,\n MutationParameters,\n OperationType,\n} from 'relay-runtime';\nimport RoutingContext from '@plumile/router/routing/RoutingContext.js';\nimport useLocation from '@plumile/router/routing/useLocation.js';\nimport { resetRelayStore } from '@plumile/relay/environment.js';\n\nimport { AdminShellLayout } from '@plumile/ui/admin/templates/admin_shell_layout/AdminShellLayout.js';\nimport { ToastProvider } from '@plumile/ui/atomic/molecules/toast/ToastProvider.js';\nimport { GlobalSearchInput } from '@plumile/ui/backoffice/molecules/global_search_input/GlobalSearchInput.js';\nimport { SidebarProfileMenu } from '@plumile/ui/components/navigation/sidebar/SidebarProfileMenu.js';\n\nimport { useBackofficeReactTranslation } from '../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeConfig } from '../provider/BackofficeConfigContext.js';\nimport type { LogoutResponse, LogoutVariables } from '../hooks/useAuth.js';\nimport { useBackofficeSidebarPins } from '../hooks/useBackofficeSidebarPins.js';\nimport { useSidebarGroupCollapse } from '../hooks/useSidebarGroupCollapse.js';\nimport { buildSidebarSections } from '../components/backoffice/layout/buildSidebarSections.js';\nimport { BackofficeContentBoundary } from '../components/backoffice/routing/BackofficeContentBoundary.js';\nimport {\n resolveActiveEntityId,\n resolveSidebarGroups,\n resolveVisibleEntityIds,\n} from '../components/backoffice/layout/sidebarUtils.js';\nimport { BackofficeTopbarPortalContextProvider } from '../components/backoffice/layout/breadcrumb/BackofficeTopbarPortalContext.js';\nimport { BackofficePermissionsProvider } from '../components/backoffice/layout/BackofficePermissionsContext.js';\nimport {\n mapViewerToSidebarProfileView,\n type BackofficeViewerIdentity,\n} from '../components/backoffice/layout/mapViewerToSidebarProfileView.js';\nimport { useRelayEnvironment } from '../relay/useRelayEnvironment.js';\nimport { getBackofficeLoginPath } from '../router/backofficeAuthPaths.js';\nimport type { BackofficeSidebarRecentItem } from '../provider/types.js';\n\nexport type BackofficeLayoutPageProps = {\n children: ReactNode;\n permissionsQuery?: GraphQLTaggedNode;\n prepared?: PreloadedQuery<OperationType> | null;\n authStatus?: {\n isLoggedIn?: boolean | null;\n me?: BackofficeViewerIdentity | null;\n } | null;\n activeGroupId?: string | null;\n};\n\ntype LayoutShellProps = {\n children: ReactNode;\n permissions: unknown;\n authStatus?: {\n isLoggedIn?: boolean | null;\n me?: BackofficeViewerIdentity | null;\n } | null;\n activeGroupId?: string | null;\n};\n\nconst DEFAULT_RECENT_ITEMS_STORAGE_KEY = 'plumile:backoffice:recent-items';\nconst DEFAULT_SIDEBAR_PREFS_STORAGE_KEY = 'plumile:backoffice:sidebar';\n\nconst readRecentItems = (\n storageKey: string,\n): readonly BackofficeSidebarRecentItem[] => {\n if (typeof window === 'undefined') {\n return [];\n }\n try {\n const raw = window.localStorage.getItem(storageKey);\n if (raw == null) {\n return [];\n }\n const parsed = JSON.parse(raw) as unknown;\n if (!Array.isArray(parsed)) {\n return [];\n }\n return parsed.filter((item): item is BackofficeSidebarRecentItem => {\n if (item == null || typeof item !== 'object') {\n return false;\n }\n const candidate = item as Partial<BackofficeSidebarRecentItem>;\n return (\n (candidate.kind === 'entity' || candidate.kind === 'tool') &&\n typeof candidate.id === 'string' &&\n typeof candidate.label === 'string' &&\n typeof candidate.href === 'string' &&\n typeof candidate.visitedAt === 'number'\n );\n });\n } catch {\n return [];\n }\n};\n\nconst writeRecentItems = (\n storageKey: string,\n items: readonly BackofficeSidebarRecentItem[],\n): void => {\n if (typeof window === 'undefined') {\n return;\n }\n try {\n window.localStorage.setItem(storageKey, JSON.stringify(items));\n } catch {\n // Ignore storage quota / privacy mode failures.\n }\n};\n\nconst BackofficeLayoutShell = ({\n children,\n permissions,\n authStatus,\n activeGroupId,\n}: LayoutShellProps): JSX.Element => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const { pathname } = useLocation();\n const routing = useContext(RoutingContext);\n const relayEnvironment = useRelayEnvironment();\n const {\n auth: authConfig,\n basePath,\n dashboards,\n entities,\n sidebar,\n } = useBackofficeConfig();\n const [sidebarQuery, setSidebarQuery] = useState('');\n const sidebarPreferencesStorageKey =\n sidebar?.preferences?.storageKey ?? DEFAULT_SIDEBAR_PREFS_STORAGE_KEY;\n const persistSidebarCollapsed =\n sidebar?.preferences?.persistCollapsed === true;\n const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(() => {\n if (!persistSidebarCollapsed || typeof window === 'undefined') {\n return false;\n }\n try {\n return (\n window.localStorage.getItem(\n `${sidebarPreferencesStorageKey}:collapsed`,\n ) === 'true'\n );\n } catch {\n return false;\n }\n });\n const [isSigningOut, setIsSigningOut] = useState(false);\n const [topbarTarget, setTopbarTarget] = useState<HTMLDivElement | null>(null);\n const recentItemsConfig = sidebar?.recentItems;\n const recentItemsEnabled = recentItemsConfig?.enabled === true;\n const recentItemsStorageKey =\n recentItemsConfig?.storageKey ?? DEFAULT_RECENT_ITEMS_STORAGE_KEY;\n const recentItemsMaxItems = recentItemsConfig?.maxItems ?? 8;\n const [recentItems, setRecentItems] = useState<\n readonly BackofficeSidebarRecentItem[]\n >(() => {\n if (!recentItemsEnabled) {\n return [];\n }\n return readRecentItems(recentItemsStorageKey);\n });\n\n useEffect(() => {\n if (!persistSidebarCollapsed || typeof window === 'undefined') {\n return;\n }\n try {\n window.localStorage.setItem(\n `${sidebarPreferencesStorageKey}:collapsed`,\n String(isSidebarCollapsed),\n );\n } catch {\n // Ignore storage quota / privacy mode failures.\n }\n }, [\n isSidebarCollapsed,\n persistSidebarCollapsed,\n sidebarPreferencesStorageKey,\n ]);\n\n const groups = useMemo(() => {\n return resolveSidebarGroups(entities, sidebar);\n }, [entities, sidebar]);\n\n const groupIds = useMemo(() => {\n return Object.keys(groups);\n }, [groups]);\n\n const defaultCollapsedByGroupId = useMemo(() => {\n return Object.fromEntries(\n Object.entries(groups).map(([groupId, group]) => {\n return [groupId, group.behavior?.defaultCollapsed ?? true];\n }),\n );\n }, [groups]);\n\n const visibleEntityIds = useMemo(() => {\n return resolveVisibleEntityIds(groups, entities, sidebar, permissions);\n }, [entities, groups, permissions, sidebar]);\n\n const activeEntityId = useMemo(() => {\n return resolveActiveEntityId(pathname, entities);\n }, [entities, pathname]);\n\n useEffect(() => {\n if (!recentItemsEnabled || activeEntityId == null) {\n return;\n }\n const config = entities[activeEntityId];\n if (config == null) {\n return;\n }\n if (config.kind !== 'tool' && !config.hasList) {\n return;\n }\n const href = config.routes.list;\n let kind: BackofficeSidebarRecentItem['kind'] = 'entity';\n if (config.kind === 'tool') {\n kind = 'tool';\n }\n const item: BackofficeSidebarRecentItem = {\n kind,\n id: activeEntityId,\n label: config.label(tApp),\n href,\n visitedAt: Date.now(),\n };\n setRecentItems((prev) => {\n const next = [\n item,\n ...prev.filter((entry) => {\n return entry.id !== item.id || entry.kind !== item.kind;\n }),\n ].slice(0, recentItemsMaxItems);\n writeRecentItems(recentItemsStorageKey, next);\n return next;\n });\n }, [\n activeEntityId,\n entities,\n recentItemsEnabled,\n recentItemsMaxItems,\n recentItemsStorageKey,\n tApp,\n ]);\n\n const pinningEnabled = sidebar?.pinnedItems?.enabled === true;\n\n const {\n pins,\n toggle: togglePin,\n reorder: reorderPin,\n } = useBackofficeSidebarPins({\n enabled: pinningEnabled,\n storageKey: sidebar?.pinnedItems?.storageKey,\n visibleEntityIds,\n });\n\n let sidebarPinnedEntityIds: readonly string[] | undefined;\n let sidebarTogglePin: ((entityId: string) => void) | undefined;\n let sidebarReorderPin: ((fromId: string, toId: string) => void) | undefined;\n if (pinningEnabled) {\n sidebarPinnedEntityIds = pins;\n sidebarTogglePin = togglePin;\n sidebarReorderPin = reorderPin;\n }\n\n let groupCollapseStorageKey: string | undefined;\n if (sidebar?.preferences?.storageKey != null) {\n groupCollapseStorageKey = `${sidebar.preferences.storageKey}:groups`;\n }\n\n const { collapsedByGroupId, setCollapsed } = useSidebarGroupCollapse({\n groupIds,\n activeGroupId,\n defaultCollapsedByGroupId,\n persist: sidebar?.preferences?.persistGroups === true,\n storageKey: groupCollapseStorageKey,\n });\n\n const sections = useMemo(() => {\n return buildSidebarSections({\n basePath,\n pathname,\n entities,\n dashboards,\n sidebar,\n permissions,\n searchQuery: sidebarQuery,\n tApp,\n t,\n pinnedEntityIds: sidebarPinnedEntityIds,\n recentItems,\n onTogglePin: sidebarTogglePin,\n onReorderPin: sidebarReorderPin,\n collapsedByGroupId,\n onGroupCollapsedChange: setCollapsed,\n sidebarCollapsed: false,\n });\n }, [\n basePath,\n collapsedByGroupId,\n entities,\n dashboards,\n pathname,\n permissions,\n recentItems,\n setCollapsed,\n sidebar,\n sidebarPinnedEntityIds,\n sidebarQuery,\n sidebarReorderPin,\n sidebarTogglePin,\n t,\n tApp,\n ]);\n\n const mobileSections = useMemo(() => {\n return buildSidebarSections({\n basePath,\n pathname,\n entities,\n dashboards,\n sidebar,\n permissions,\n searchQuery: sidebarQuery,\n tApp,\n t,\n pinnedEntityIds: sidebarPinnedEntityIds,\n recentItems,\n onTogglePin: sidebarTogglePin,\n onReorderPin: sidebarReorderPin,\n collapsedByGroupId,\n onGroupCollapsedChange: setCollapsed,\n sidebarCollapsed: false,\n });\n }, [\n basePath,\n collapsedByGroupId,\n entities,\n dashboards,\n pathname,\n permissions,\n recentItems,\n setCollapsed,\n sidebar,\n sidebarPinnedEntityIds,\n sidebarQuery,\n sidebarReorderPin,\n sidebarTogglePin,\n t,\n tApp,\n ]);\n\n const handleSignOut = useCallback(() => {\n if (isSigningOut) {\n return;\n }\n\n type LogoutMutation = MutationParameters & {\n response: LogoutResponse;\n variables: LogoutVariables;\n };\n\n setIsSigningOut(true);\n\n const runSignOut = async (): Promise<void> => {\n try {\n const config = await authConfig.logout.load();\n await new Promise<void>((resolve, reject) => {\n commitMutation<LogoutMutation>(relayEnvironment, {\n mutation: config.logoutMutation,\n variables: {},\n onCompleted: () => {\n resolve();\n },\n onError: (error) => {\n reject(error);\n },\n });\n });\n localStorage.removeItem('auth_token');\n localStorage.removeItem('remember_me');\n resetRelayStore();\n routing?.history.push({ pathname: getBackofficeLoginPath(basePath) });\n } finally {\n setIsSigningOut(false);\n }\n };\n\n runSignOut().catch(() => {\n /* noop */\n });\n }, [authConfig.logout, basePath, isSigningOut, relayEnvironment, routing]);\n\n const viewer = authStatus?.me ?? null;\n const sidebarProfile = useMemo(() => {\n return mapViewerToSidebarProfileView({\n viewer,\n unknownUserLabel: t('sidebar.profile.unknownUser'),\n });\n }, [t, viewer]);\n\n const sidebarFooter = (\n <SidebarProfileMenu\n collapsed={false}\n viewer={sidebarProfile}\n labels={{\n sectionTitle: t('sidebar.profile.title'),\n menuAriaLabel: t('sidebar.profile.menuAriaLabel'),\n signOut: t('sidebar.profile.actions.signOut'),\n }}\n onSignOut={handleSignOut}\n isSigningOut={isSigningOut}\n />\n );\n\n const mobileSidebarFooter = (\n <SidebarProfileMenu\n collapsed={false}\n viewer={sidebarProfile}\n labels={{\n sectionTitle: t('sidebar.profile.title'),\n menuAriaLabel: t('sidebar.profile.menuAriaLabel'),\n signOut: t('sidebar.profile.actions.signOut'),\n }}\n onSignOut={handleSignOut}\n isSigningOut={isSigningOut}\n />\n );\n\n let contentNode: JSX.Element | null = null;\n if (topbarTarget != null) {\n contentNode = (\n <BackofficeContentBoundary>{children}</BackofficeContentBoundary>\n );\n }\n\n const sidebarSearchNode = (\n <GlobalSearchInput\n value={sidebarQuery}\n onChange={setSidebarQuery}\n placeholder={t('sidebar.search.placeholder')}\n ariaLabel={t('sidebar.search.placeholder')}\n />\n );\n\n return (\n <ToastProvider>\n <AdminShellLayout\n sidebar={{\n sections,\n search: sidebarSearchNode,\n footer: sidebarFooter,\n isCollapsed: isSidebarCollapsed,\n onCollapsedChange: setIsSidebarCollapsed,\n collapseToggleLabel: t('sidebar.actions.collapseSidebar'),\n expandToggleLabel: t('sidebar.actions.expandSidebar'),\n navigationAriaLabel: t('sidebar.navigationAriaLabel'),\n }}\n mobileSidebar={{\n sections: mobileSections,\n search: sidebarSearchNode,\n footer: mobileSidebarFooter,\n isCollapsed: false,\n hideCollapseToggle: true,\n navigationAriaLabel: t('sidebar.navigationAriaLabel'),\n }}\n topbar={{\n breadcrumb: <div ref={setTopbarTarget} />,\n }}\n contentScrollMode=\"contained\"\n >\n <BackofficePermissionsProvider permissions={permissions}>\n <BackofficeTopbarPortalContextProvider\n value={{\n target: topbarTarget,\n dashboardHref: basePath,\n dashboardLabel: t('sidebar.items.dashboard'),\n }}\n >\n {contentNode}\n </BackofficeTopbarPortalContextProvider>\n </BackofficePermissionsProvider>\n </AdminShellLayout>\n </ToastProvider>\n );\n};\n\ntype LayoutWithPermissionsProps = {\n children: ReactNode;\n permissionsQuery: GraphQLTaggedNode;\n prepared: PreloadedQuery<OperationType>;\n authStatus?: {\n isLoggedIn?: boolean | null;\n me?: BackofficeViewerIdentity | null;\n } | null;\n activeGroupId?: string | null;\n};\n\nconst LayoutWithPermissions = ({\n children,\n permissionsQuery,\n prepared,\n authStatus,\n activeGroupId,\n}: LayoutWithPermissionsProps): JSX.Element => {\n const permissions = usePreloadedQuery(permissionsQuery, prepared);\n\n return (\n <BackofficeLayoutShell\n permissions={permissions}\n authStatus={authStatus}\n activeGroupId={activeGroupId}\n >\n {children}\n </BackofficeLayoutShell>\n );\n};\n\nexport const BackofficeLayoutPage = ({\n children,\n permissionsQuery,\n prepared,\n authStatus,\n activeGroupId,\n}: BackofficeLayoutPageProps): JSX.Element => {\n if (permissionsQuery != null && prepared != null) {\n return (\n <LayoutWithPermissions\n permissionsQuery={permissionsQuery}\n prepared={prepared}\n authStatus={authStatus}\n activeGroupId={activeGroupId}\n >\n {children}\n </LayoutWithPermissions>\n );\n }\n\n return (\n <BackofficeLayoutShell\n permissions={null}\n authStatus={authStatus}\n activeGroupId={activeGroupId}\n >\n {children}\n </BackofficeLayoutShell>\n );\n};\n\nexport default BackofficeLayoutPage;\n"],"mappings":"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"}
@@ -12,12 +12,12 @@ import { StrictMode as d, useEffect as f, useMemo as p, useRef as m, useState as
12
12
  import { jsx as g, jsxs as _ } from "react/jsx-runtime";
13
13
  import { I18nextProvider as v } from "react-i18next";
14
14
  import y from "@plumile/router/routing/RoutingContext.js";
15
- import { RelayProvider as b, configureRelayEnvironment as x, useRelayOperationActivity as S } from "@plumile/relay";
16
- import { createInstance as C } from "i18next";
17
- import w from "@plumile/router/routing/createRouter.js";
18
- import T from "@plumile/router/routing/RouterRenderer.js";
19
- import { BackofficeThemeProvider as E } from "@plumile/ui/admin/theme/BackofficeThemeProvider.js";
20
- import { RoutePendingBar as D } from "@plumile/ui/components/routing/RoutePendingBar.js";
15
+ import { createInstance as b } from "i18next";
16
+ import x from "@plumile/router/routing/createRouter.js";
17
+ import S from "@plumile/router/routing/RouterRenderer.js";
18
+ import { BackofficeThemeProvider as C } from "@plumile/ui/admin/theme/BackofficeThemeProvider.js";
19
+ import { RoutePendingBar as w } from "@plumile/ui/components/routing/RoutePendingBar.js";
20
+ import { RelayProvider as T, configureRelayEnvironment as E, useRelayOperationActivity as D } from "@plumile/relay";
21
21
  //#region src/provider/BackofficeProvider.tsx
22
22
  var O = (e) => e.trim() === "" || e === "/" ? "/" : e.startsWith("/") ? e.endsWith("/") ? e.slice(0, -1) : e : `/${e}`, k = (e, t) => {
23
23
  let n = O(t), r = O(e);
@@ -32,7 +32,7 @@ var O = (e) => e.trim() === "" || e === "/" ? "/" : e.startsWith("/") ? e.endsWi
32
32
  }])), j = ({ routes: e, context: t, instrumentations: n }) => {
33
33
  let [r, i] = h(null), a = m(null);
34
34
  return f(() => {
35
- let r = w(e, {
35
+ let r = x(e, {
36
36
  context: t,
37
37
  instrumentations: n
38
38
  });
@@ -45,41 +45,41 @@ var O = (e) => e.trim() === "" || e === "/" ? "/" : e.startsWith("/") ? e.endsWi
45
45
  e
46
46
  ]), r;
47
47
  }, M = ({ routes: e, instrumentations: t }) => {
48
- let r = i(), a = S(), o = j({
48
+ let r = i(), a = D(), o = j({
49
49
  routes: e,
50
50
  context: p(() => ({ relayEnvironment: r }), [r]),
51
51
  instrumentations: t
52
52
  });
53
53
  return o == null ? /* @__PURE__ */ g(n, {}) : /* @__PURE__ */ g(y.Provider, {
54
54
  value: o.context,
55
- children: /* @__PURE__ */ g(T, {
55
+ children: /* @__PURE__ */ g(S, {
56
56
  enableTransition: !0,
57
57
  externalPending: a.pendingCount > 0,
58
58
  fallback: /* @__PURE__ */ g(n, {}),
59
- pending: /* @__PURE__ */ g(D, {})
59
+ pending: /* @__PURE__ */ g(w, {})
60
60
  })
61
61
  });
62
62
  }, N = (n) => {
63
- let i = O(n.basePath ?? "/"), m = u(i), y = p(() => A(n.entityManifest, i), [i, n.entityManifest]), S = p(() => c(y, { basePath: i }), [i, y]), w = n.graphql, T = p(() => t(n.dashboards), [n.dashboards]);
63
+ let i = O(n.basePath ?? "/"), m = u(i), y = p(() => A(n.entityManifest, i), [i, n.entityManifest]), x = p(() => c(y, { basePath: i }), [i, y]), S = n.graphql, w = p(() => t(n.dashboards), [n.dashboards]);
64
64
  f(() => {
65
- let e = w.httpUrl ?? w.endpoint, t = w.wsUrl ?? w.wsEndpoint;
66
- x({
65
+ let e = S.httpUrl ?? S.endpoint, t = S.wsUrl ?? S.wsEndpoint;
66
+ E({
67
67
  httpUrl: e,
68
68
  wsUrl: t,
69
- getDataId: w.getDataId,
70
- logEvents: w.logEvents,
71
- getAuthHeaders: w.getAuthHeaders
69
+ getDataId: S.getDataId,
70
+ logEvents: S.logEvents,
71
+ getAuthHeaders: S.getAuthHeaders
72
72
  });
73
73
  }, [
74
- w.endpoint,
75
- w.getAuthHeaders,
76
- w.getDataId,
77
- w.httpUrl,
78
- w.logEvents,
79
- w.wsEndpoint,
80
- w.wsUrl
74
+ S.endpoint,
75
+ S.getAuthHeaders,
76
+ S.getDataId,
77
+ S.httpUrl,
78
+ S.logEvents,
79
+ S.wsEndpoint,
80
+ S.wsUrl
81
81
  ]);
82
- let D = p(() => o(n.i18n?.resources ?? {}), [n.i18n?.resources]), k = p(() => n.i18n?.instance ?? C(), [n.i18n?.instance]), [j, N] = h(k.isInitialized);
82
+ let D = p(() => o(n.i18n?.resources ?? {}), [n.i18n?.resources]), k = p(() => n.i18n?.instance ?? b(), [n.i18n?.instance]), [j, N] = h(k.isInitialized);
83
83
  f(() => {
84
84
  let e = !0, t = () => {
85
85
  e && N(!0);
@@ -128,43 +128,43 @@ var O = (e) => e.trim() === "" || e === "/" ? "/" : e.startsWith("/") ? e.endsWi
128
128
  basePath: i,
129
129
  entities: y,
130
130
  entityManifest: y,
131
- entityRegistry: S,
131
+ entityRegistry: x,
132
132
  filterColumnAliases: n.filterColumnAliases,
133
133
  sidebar: n.sidebar,
134
134
  dashboard: n.dashboard,
135
- dashboards: T,
135
+ dashboards: w,
136
136
  auth: n.auth,
137
137
  graphql: n.graphql
138
138
  }), [
139
139
  i,
140
140
  n.auth,
141
141
  n.dashboard,
142
- T,
142
+ w,
143
143
  y,
144
- S,
144
+ x,
145
145
  n.filterColumnAliases,
146
146
  n.graphql,
147
147
  n.sidebar
148
148
  ]), F = p(() => s({
149
149
  basePath: i,
150
150
  entityManifest: y,
151
- entityRegistry: S,
151
+ entityRegistry: x,
152
152
  sidebar: n.sidebar,
153
153
  auth: n.auth,
154
154
  dashboard: n.dashboard,
155
- dashboards: T,
155
+ dashboards: w,
156
156
  toolsOperationPage: n.toolsOperationPage
157
157
  }), [
158
158
  i,
159
159
  y,
160
- S,
160
+ x,
161
161
  n.auth,
162
162
  n.dashboard,
163
- T,
163
+ w,
164
164
  n.toolsOperationPage,
165
165
  n.sidebar
166
166
  ]), I = /* @__PURE__ */ g(r, { label: "Loading..." });
167
- return j && m && (I = /* @__PURE__ */ g(E, { children: /* @__PURE__ */ g(b, { children: /* @__PURE__ */ _(e, {
167
+ return j && m && (I = /* @__PURE__ */ g(C, { children: /* @__PURE__ */ g(T, { children: /* @__PURE__ */ _(e, {
168
168
  value: P,
169
169
  children: [n.overlay, /* @__PURE__ */ g(l, { children: /* @__PURE__ */ g(M, {
170
170
  routes: F,
@@ -56,11 +56,11 @@ var { loadQuery: f, usePreloadedQuery: p } = c, m = u("WrapperPage", async () =>
56
56
  return e.detailPages?.find((e) => I(e.pathSegment) === n) ?? null;
57
57
  }, B = (e, t) => z(e, t)?.id ?? t, V = d;
58
58
  function H(a) {
59
- let { basePath: o, entityManifest: c, entityRegistry: l, sidebar: u, auth: d, dashboard: p } = a, N = r(a.dashboards), I = M(o), z = P(I, "login"), H = P(I, "login/reset"), U = P(I, "login/reset/complete"), oe = P(I, "verify-email"), se = P(I, "accept-invitation"), ce = F(I, "login"), W = t(c, u), le = n(W, u), ue = e(W, u), G = /* @__PURE__ */ new Map();
60
- ue.forEach((e, t) => {
59
+ let { basePath: o, entityManifest: c, entityRegistry: l, sidebar: u, auth: d, dashboard: p } = a, m = r(a.dashboards), N = M(o), I = P(N, "login"), z = P(N, "login/reset"), H = P(N, "login/reset/complete"), U = P(N, "verify-email"), oe = P(N, "accept-invitation"), se = F(N, "login"), W = t(c, u), ce = n(W, u), le = e(W, u), G = /* @__PURE__ */ new Map();
60
+ le.forEach((e, t) => {
61
61
  G.set(t, e.groupId);
62
62
  });
63
- let K = /* @__PURE__ */ new WeakMap(), q = /* @__PURE__ */ new WeakMap(), J = u?.permissionsQuery, de = async ({ context: e }) => {
63
+ let K = /* @__PURE__ */ new WeakMap(), q = /* @__PURE__ */ new WeakMap(), J = u?.permissionsQuery, ue = async ({ context: e }) => {
64
64
  let t = await d.session.load();
65
65
  return {
66
66
  permissionsQuery: J == null ? null : f(e.relayEnvironment, J, {}),
@@ -72,7 +72,7 @@ function H(a) {
72
72
  }, X = () => p == null ? null : { dashboardId: "dashboard" }, Z = ({ prepared: e, Component: t }) => t == null ? null : /* @__PURE__ */ s(t, { prepared: e }), Q = ({ children: e, prepared: t, Component: n }) => n == null ? null : /* @__PURE__ */ s(n, {
73
73
  prepared: t,
74
74
  children: e
75
- }), fe = V({
75
+ }), de = V({
76
76
  path: "",
77
77
  resourcePage: T,
78
78
  prepare: X,
@@ -83,7 +83,7 @@ function H(a) {
83
83
  prepare: Y,
84
84
  render: Z
85
85
  })]
86
- }), pe = V({
86
+ }), fe = V({
87
87
  path: "dashboard",
88
88
  resourcePage: T,
89
89
  prepare: X,
@@ -94,7 +94,7 @@ function H(a) {
94
94
  prepare: Y,
95
95
  render: Z
96
96
  })]
97
- }), me = N.map((e) => {
97
+ }), pe = m.map((e) => {
98
98
  let t = V({
99
99
  path: "",
100
100
  resourcePage: w,
@@ -118,9 +118,9 @@ function H(a) {
118
118
  render: Q,
119
119
  children: [t]
120
120
  });
121
- }), he = Object.values(c).filter((e) => e.kind === "list-detail"), ge = le.map((e) => {
121
+ }), me = Object.values(c).filter((e) => e.kind === "list-detail"), he = ce.map((e) => {
122
122
  let t = V({
123
- path: L(e.hub.href, I),
123
+ path: L(e.hub.href, N),
124
124
  resourcePage: D,
125
125
  prepare: () => ({
126
126
  hubId: e.hub.id,
@@ -129,8 +129,8 @@ function H(a) {
129
129
  render: ({ prepared: e, Component: t }) => t == null ? null : /* @__PURE__ */ s(t, { prepared: e })
130
130
  });
131
131
  return e.groupId != null && q.set(t, e.groupId), t;
132
- }), _e = he.map((e) => {
133
- let t = e.routes.list, n = L(t, I), r = [], a = ({ match: t }) => {
132
+ }), ge = me.map((e) => {
133
+ let t = e.routes.list, n = L(t, N), r = [], a = ({ match: t }) => {
134
134
  let n = String(t?.params.id ?? ""), r = typeof t?.params.pagePath == "string" ? t.params.pagePath : null, a = r == null ? e.defaultDetailPageId : B(e, r);
135
135
  return /* @__PURE__ */ s(i, {
136
136
  entityManifest: e,
@@ -292,7 +292,6 @@ function H(a) {
292
292
  children: [
293
293
  V({
294
294
  path: "",
295
- resourcePage: m,
296
295
  prepare: ({ variables: t }) => {
297
296
  let n = String(t.id ?? "").trim();
298
297
  return { redirectTo: n === "" ? null : e.routes.detailPage(n, e.defaultDetailPageId) };
@@ -385,11 +384,10 @@ function H(a) {
385
384
  return K.set(d, e.id), r.push(d), V({
386
385
  path: n,
387
386
  children: r,
388
- resourcePage: m,
389
387
  suspenseBoundary: "segment"
390
388
  });
391
- }), ve = Object.values(c).filter((e) => e.kind === "tool").map((e) => {
392
- let t = L(e.routes.list, I), n = V({
389
+ }), _e = Object.values(c).filter((e) => e.kind === "tool").map((e) => {
390
+ let t = L(e.routes.list, N), n = V({
393
391
  path: "",
394
392
  resourcePage: a.toolsOperationPage ?? null,
395
393
  prepare: async () => {
@@ -430,12 +428,12 @@ function H(a) {
430
428
  children: [n]
431
429
  });
432
430
  return K.set(r, e.id), r;
433
- }), ye = V({
434
- path: I,
431
+ }), ve = V({
432
+ path: N,
435
433
  resourcePage: h,
436
434
  prepareSearchBehavior: "path",
437
435
  suspenseBoundary: "segment",
438
- prepare: de,
436
+ prepare: ue,
439
437
  render: ({ children: e, prepared: t, route: n, Component: r }) => {
440
438
  if (r == null) return null;
441
439
  let i = t, a = R(n, K), o = a == null ? R(n, q) : G.get(a) ?? null, c = r, l = d.session.get()?.authStatusQuery ?? null;
@@ -446,7 +444,7 @@ function H(a) {
446
444
  activeGroupId: o,
447
445
  authStatusQuery: l,
448
446
  authStatusPrepared: i.authStatusQuery,
449
- loginRedirectPath: ce,
447
+ loginRedirectPath: se,
450
448
  children: e
451
449
  }) : /* @__PURE__ */ s(ae, {
452
450
  Component: c,
@@ -457,16 +455,16 @@ function H(a) {
457
455
  });
458
456
  },
459
457
  children: [
460
- fe,
458
+ de,
459
+ ...he,
461
460
  ...ge,
462
461
  ..._e,
463
- ...ve,
464
- ...me,
465
- pe
462
+ ...pe,
463
+ fe
466
464
  ]
467
465
  }), $ = [
468
466
  V({
469
- path: z,
467
+ path: I,
470
468
  resourcePage: ne,
471
469
  prepare: async ({ context: e }) => {
472
470
  let t = await d.login.load();
@@ -475,30 +473,30 @@ function H(a) {
475
473
  render: ({ prepared: e, Component: t }) => t == null ? null : /* @__PURE__ */ s(t, { prepared: e })
476
474
  }),
477
475
  V({
478
- path: H,
476
+ path: z,
479
477
  resourcePage: re,
480
478
  prepare: async () => (await d.passwordResetRequest.load(), null),
481
479
  render: ({ Component: e }) => e == null ? null : /* @__PURE__ */ s(e, {})
482
480
  }),
483
481
  V({
484
- path: U,
482
+ path: H,
485
483
  resourcePage: ie,
486
484
  prepare: async () => (await d.passwordResetComplete.load(), null),
487
485
  render: ({ Component: e }) => e == null ? null : /* @__PURE__ */ s(e, {})
488
486
  }),
489
487
  V({
490
- path: oe,
488
+ path: U,
491
489
  resourcePage: O,
492
490
  prepare: async () => (await d.verifyEmail.load(), null),
493
491
  render: ({ Component: e }) => e == null ? null : /* @__PURE__ */ s(e, {})
494
492
  })
495
493
  ];
496
494
  return (d.hasAcceptInvitation === !0 || d.acceptInvitation != null) && $.push(V({
497
- path: se,
495
+ path: oe,
498
496
  resourcePage: k,
499
497
  prepare: async () => (await d.acceptInvitation?.load(), null),
500
498
  render: ({ Component: e }) => e == null ? null : /* @__PURE__ */ s(e, {})
501
- })), $.push(ye), $;
499
+ })), $.push(ve), $;
502
500
  }
503
501
  var U = {
504
502
  normalizeBaseSegment: M,