@plumile/backoffice-react 0.1.191 → 0.1.192

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 (228) hide show
  1. package/lib/esm/auth/authRefreshNotice.css.js +0 -1
  2. package/lib/esm/auth/login/PasskeyLoginForm.js +2 -1
  3. package/lib/esm/auth/login/PasskeyLoginForm.js.map +1 -1
  4. package/lib/esm/auth/login/loginPage.css.js +0 -2
  5. package/lib/esm/components/backoffice/actions/BackofficeEntityActionFormDialog.js +5 -2
  6. package/lib/esm/components/backoffice/actions/BackofficeEntityActionFormDialog.js.map +1 -1
  7. package/lib/esm/components/backoffice/actions/backofficeEntityActionFormDialog.css.js +0 -1
  8. package/lib/esm/components/backoffice/billing/backofficeBillingUsageChart.css.js +0 -1
  9. package/lib/esm/components/backoffice/detail/backofficeDetailBadgeRow.css.js +0 -1
  10. package/lib/esm/components/backoffice/detail/backofficeDetailErrorList.css.js +0 -1
  11. package/lib/esm/components/backoffice/detail/backofficeDetailLayout.css.js +0 -1
  12. package/lib/esm/components/backoffice/detail/backofficeDetailRelationLink.css.js +0 -1
  13. package/lib/esm/components/backoffice/detail/backofficeDetailRelationList.css.js +0 -1
  14. package/lib/esm/components/backoffice/detail/backofficeEntitySummaryHeader.css.js +0 -1
  15. package/lib/esm/components/backoffice/detail/backofficeRelationsSummaryGrid.css.js +0 -1
  16. package/lib/esm/components/backoffice/filters/backofficeFilterAction.css.js +0 -1
  17. package/lib/esm/components/backoffice/layout/breadcrumb/backofficeTopbarBreadcrumb.css.js +0 -2
  18. package/lib/esm/components/backoffice/layout/buildSidebarSections.js +10 -7
  19. package/lib/esm/components/backoffice/layout/buildSidebarSections.js.map +1 -1
  20. package/lib/esm/components/backoffice/layout/sidebarUtils.js +1 -1
  21. package/lib/esm/components/backoffice/layout/sidebarUtils.js.map +1 -1
  22. package/lib/esm/components/backoffice/links/backofficeLink.css.js +0 -1
  23. package/lib/esm/components/backoffice/list/RowFlagsCell.css.js +0 -1
  24. package/lib/esm/components/backoffice/pickers/entityIdPickerDialog.css.js +0 -1
  25. package/lib/esm/components/backoffice/refs/backofficeEntityIdRef.css.js +0 -1
  26. package/lib/esm/components/backoffice/routing/backofficeContentBoundary.css.js +0 -1
  27. package/lib/esm/components/backoffice/routing/backofficeContentError.css.js +0 -1
  28. package/lib/esm/components/backoffice/routing/backofficeContentFallback.css.js +0 -1
  29. package/lib/esm/components/backoffice/routing/backofficeRouteFallback.css.js +0 -1
  30. package/lib/esm/components/backoffice/scaffolds/BackofficeEntityListScaffold.js +17 -17
  31. package/lib/esm/components/backoffice/scaffolds/BackofficeEntityListScaffold.js.map +1 -1
  32. package/lib/esm/components/backoffice/scaffolds/backofficeEntityListScaffold.css.js +0 -1
  33. package/lib/esm/components/backoffice/scaffolds/backofficeTabbedDetailShell.css.js +0 -1
  34. package/lib/esm/components/backoffice/shared/backofficeFilterableCell.css.js +0 -1
  35. package/lib/esm/components/backoffice/shared/backofficeInlineFilterRow.css.js +0 -1
  36. package/lib/esm/components/backoffice/tools/backofficeToolsForm.css.js +0 -1
  37. package/lib/esm/components/backoffice/tools/backofficeToolsJsonForm.css.js +0 -1
  38. package/lib/esm/filters/filterHelpers.js +1 -1
  39. package/lib/esm/filters/filterHelpers.js.map +1 -1
  40. package/lib/esm/hooks/useBackofficeSidebarPins.js +2 -1
  41. package/lib/esm/hooks/useBackofficeSidebarPins.js.map +1 -1
  42. package/lib/esm/hooks/useSidebarGroupCollapse.js +2 -1
  43. package/lib/esm/hooks/useSidebarGroupCollapse.js.map +1 -1
  44. package/lib/esm/node_modules/relay-test-utils/lib/RelayMockPayloadGenerator.js +2 -2
  45. package/lib/esm/node_modules/relay-test-utils/lib/RelayMockPayloadGenerator.js.map +1 -1
  46. package/lib/esm/node_modules/relay-test-utils/lib/RelayModernMockEnvironment.js +1 -1
  47. package/lib/esm/node_modules/relay-test-utils/lib/RelayModernMockEnvironment.js.map +1 -1
  48. package/lib/esm/pages/BackofficeEntityDetailPage.helpers.js +1 -1
  49. package/lib/esm/pages/BackofficeEntityDetailPage.helpers.js.map +1 -1
  50. package/lib/esm/pages/BackofficeEntityDetailPage.js +1 -1
  51. package/lib/esm/pages/BackofficeEntityDetailPage.js.map +1 -1
  52. package/lib/esm/pages/BackofficeEntityListPage.js +1 -1
  53. package/lib/esm/pages/BackofficeEntityListPage.js.map +1 -1
  54. package/lib/esm/pages/backofficeDashboardPage.css.js +0 -1
  55. package/lib/esm/pages/backofficeEntityDetailPage.css.js +0 -1
  56. package/lib/esm/pages/backofficeEntityListPage.css.js +0 -1
  57. package/lib/esm/pages/detail/pageResolution.js +1 -1
  58. package/lib/esm/pages/detail/pageResolution.js.map +1 -1
  59. package/lib/esm/provider/entityRegistry.js +15 -15
  60. package/lib/esm/provider/entityRegistry.js.map +1 -1
  61. package/lib/esm/storybook/relay/RelayStory.css.js +0 -1
  62. package/lib/esm/storybook/relay/mockResolvers.js +10 -9
  63. package/lib/esm/storybook/relay/mockResolvers.js.map +1 -1
  64. package/lib/types/auth/AuthFlows.stories.d.ts.map +1 -1
  65. package/lib/types/auth/AuthRefreshNotice.d.ts.map +1 -1
  66. package/lib/types/auth/TotpQrCode.d.ts.map +1 -1
  67. package/lib/types/auth/login/AuthPanel.d.ts.map +1 -1
  68. package/lib/types/auth/login/EmailCapturePanel.d.ts.map +1 -1
  69. package/lib/types/auth/login/LoginFlow.d.ts.map +1 -1
  70. package/lib/types/auth/login/MethodChooser.d.ts.map +1 -1
  71. package/lib/types/auth/login/MfaChallengeForm.d.ts.map +1 -1
  72. package/lib/types/auth/login/OidcButtons.d.ts.map +1 -1
  73. package/lib/types/auth/login/PasskeyLoginForm.d.ts.map +1 -1
  74. package/lib/types/auth/login/PasswordLoginPanel.d.ts.map +1 -1
  75. package/lib/types/auth/pages/AcceptInvitationScreen.d.ts.map +1 -1
  76. package/lib/types/auth/pages/PasswordResetCompleteScreen.d.ts.map +1 -1
  77. package/lib/types/auth/pages/PasswordResetRequestScreen.d.ts.map +1 -1
  78. package/lib/types/auth/pages/VerifyEmailScreen.d.ts.map +1 -1
  79. package/lib/types/components/backoffice/actions/BackofficeEntityActionFormDialog.d.ts.map +1 -1
  80. package/lib/types/components/backoffice/actions/LazyBackofficeEntityActionFormDialog.d.ts.map +1 -1
  81. package/lib/types/components/backoffice/actions/toastViewAction.d.ts.map +1 -1
  82. package/lib/types/components/backoffice/billing/BackofficeBillingUsageChart.d.ts.map +1 -1
  83. package/lib/types/components/backoffice/billing/BackofficeBillingUsageChart.stories.d.ts +18 -18
  84. package/lib/types/components/backoffice/billing/BackofficeBillingUsageChart.stories.d.ts.map +1 -1
  85. package/lib/types/components/backoffice/detail/BackofficeDetailBadgeRow.d.ts.map +1 -1
  86. package/lib/types/components/backoffice/detail/BackofficeDetailErrorList.d.ts.map +1 -1
  87. package/lib/types/components/backoffice/detail/BackofficeDetailFlagTag.d.ts.map +1 -1
  88. package/lib/types/components/backoffice/detail/BackofficeDetailPrimitives.stories.d.ts.map +1 -1
  89. package/lib/types/components/backoffice/detail/BackofficeDetailRelationList.d.ts.map +1 -1
  90. package/lib/types/components/backoffice/detail/BackofficeDetailTaggedValue.d.ts.map +1 -1
  91. package/lib/types/components/backoffice/detail/BackofficeEntitySummaryHeader.d.ts.map +1 -1
  92. package/lib/types/components/backoffice/detail/BackofficeEnumLabel.d.ts.map +1 -1
  93. package/lib/types/components/backoffice/detail/BackofficeLifecycleTimelineSection.d.ts.map +1 -1
  94. package/lib/types/components/backoffice/detail/BackofficeReferenceValue.d.ts.map +1 -1
  95. package/lib/types/components/backoffice/detail/BackofficeRelationsSummaryGrid.d.ts.map +1 -1
  96. package/lib/types/components/backoffice/detail/BackofficeStatusGroup.d.ts.map +1 -1
  97. package/lib/types/components/backoffice/detail/BackofficeStatusMetaBadge.d.ts.map +1 -1
  98. package/lib/types/components/backoffice/detail/BackofficeTokenUsageBreakdown.d.ts.map +1 -1
  99. package/lib/types/components/backoffice/detail/BackofficeUsageCostBreakdown.d.ts.map +1 -1
  100. package/lib/types/components/backoffice/detail/createBackofficeEntityLinkProps.d.ts.map +1 -1
  101. package/lib/types/components/backoffice/errors/BackofficeErrorBoundary.d.ts.map +1 -1
  102. package/lib/types/components/backoffice/errors/BackofficeErrorBoundary.stories.d.ts.map +1 -1
  103. package/lib/types/components/backoffice/filters/BackofficeFilterAction.d.ts.map +1 -1
  104. package/lib/types/components/backoffice/filters/DeferredFilterSearchInput.d.ts.map +1 -1
  105. package/lib/types/components/backoffice/filters/EntityFilterValue.d.ts.map +1 -1
  106. package/lib/types/components/backoffice/filters/EntityIdFilterField.d.ts.map +1 -1
  107. package/lib/types/components/backoffice/filters/EntityIdFilterField.stories.d.ts +1 -1
  108. package/lib/types/components/backoffice/filters/EntityIdFilterField.stories.d.ts.map +1 -1
  109. package/lib/types/components/backoffice/hub/BackofficeHubTemplate.d.ts.map +1 -1
  110. package/lib/types/components/backoffice/hub/BackofficeHubTemplate.stories.d.ts +4 -3
  111. package/lib/types/components/backoffice/hub/BackofficeHubTemplate.stories.d.ts.map +1 -1
  112. package/lib/types/components/backoffice/layout/BackofficePermissionsContext.d.ts.map +1 -1
  113. package/lib/types/components/backoffice/layout/breadcrumb/BackofficeRightPageLayout.d.ts.map +1 -1
  114. package/lib/types/components/backoffice/layout/breadcrumb/BackofficeTopbarBreadcrumb.d.ts.map +1 -1
  115. package/lib/types/components/backoffice/layout/breadcrumb/BackofficeTopbarPortal.d.ts.map +1 -1
  116. package/lib/types/components/backoffice/layout/breadcrumb/assertValidBreadcrumb.d.ts.map +1 -1
  117. package/lib/types/components/backoffice/layout/breadcrumb/buildBreadcrumbs.d.ts +1 -1
  118. package/lib/types/components/backoffice/layout/breadcrumb/buildBreadcrumbs.d.ts.map +1 -1
  119. package/lib/types/components/backoffice/layout/mapViewerToSidebarProfileView.d.ts.map +1 -1
  120. package/lib/types/components/backoffice/layout/sidebarUtils.d.ts.map +1 -1
  121. package/lib/types/components/backoffice/links/BackofficeInlineLink.d.ts.map +1 -1
  122. package/lib/types/components/backoffice/links/BackofficeLink.d.ts.map +1 -1
  123. package/lib/types/components/backoffice/links/BackofficeLinkContent.d.ts.map +1 -1
  124. package/lib/types/components/backoffice/links/BackofficeLinkLabel.d.ts.map +1 -1
  125. package/lib/types/components/backoffice/links/resolveBackofficeLink.d.ts.map +1 -1
  126. package/lib/types/components/backoffice/links/resolveBackofficeTargetIcon.d.ts.map +1 -1
  127. package/lib/types/components/backoffice/links/useBackofficeLink.d.ts.map +1 -1
  128. package/lib/types/components/backoffice/list/RowFlagsCell.d.ts.map +1 -1
  129. package/lib/types/components/backoffice/overview/BackofficeOverviewLayout.d.ts.map +1 -1
  130. package/lib/types/components/backoffice/overview/BackofficeOverviewLayout.stories.d.ts +1 -1
  131. package/lib/types/components/backoffice/overview/BackofficeOverviewLayout.stories.d.ts.map +1 -1
  132. package/lib/types/components/backoffice/pickers/EntityIdPickerDialog.d.ts.map +1 -1
  133. package/lib/types/components/backoffice/pickers/EntityIdPickerDialog.stories.d.ts +2 -1
  134. package/lib/types/components/backoffice/pickers/EntityIdPickerDialog.stories.d.ts.map +1 -1
  135. package/lib/types/components/backoffice/refs/BackofficeEntityIdRef.d.ts.map +1 -1
  136. package/lib/types/components/backoffice/refs/BackofficeEntityLink.d.ts.map +1 -1
  137. package/lib/types/components/backoffice/refs/BackofficeLazyEntityCount.d.ts.map +1 -1
  138. package/lib/types/components/backoffice/refs/BackofficeRelatedCountLink.d.ts.map +1 -1
  139. package/lib/types/components/backoffice/routing/BackofficeContentBoundary.d.ts.map +1 -1
  140. package/lib/types/components/backoffice/routing/BackofficeContentError.d.ts.map +1 -1
  141. package/lib/types/components/backoffice/routing/BackofficeContentFallback.d.ts.map +1 -1
  142. package/lib/types/components/backoffice/routing/BackofficeRouteFallback.d.ts.map +1 -1
  143. package/lib/types/components/backoffice/routing/BackofficeRoutePendingBar.d.ts.map +1 -1
  144. package/lib/types/components/backoffice/scaffolds/BackofficeEntityDetailNotFound.d.ts.map +1 -1
  145. package/lib/types/components/backoffice/scaffolds/BackofficeEntityDetailScaffold.d.ts.map +1 -1
  146. package/lib/types/components/backoffice/scaffolds/BackofficeEntityListScaffold.d.ts.map +1 -1
  147. package/lib/types/components/backoffice/scaffolds/BackofficeListFilterContext.d.ts.map +1 -1
  148. package/lib/types/components/backoffice/scaffolds/BackofficeTabbedDetailShell.d.ts.map +1 -1
  149. package/lib/types/components/backoffice/scaffolds/BackofficeTabbedDetailShell.stories.d.ts +1 -1
  150. package/lib/types/components/backoffice/scaffolds/BackofficeTabbedDetailShell.stories.d.ts.map +1 -1
  151. package/lib/types/components/backoffice/scaffolds/backofficeListScrollMode.d.ts +1 -1
  152. package/lib/types/components/backoffice/shared/BackofficeFilterableCell.d.ts.map +1 -1
  153. package/lib/types/components/backoffice/shared/BackofficeFormattedCurrency.d.ts.map +1 -1
  154. package/lib/types/components/backoffice/shared/BackofficeFormattedNumber.d.ts.map +1 -1
  155. package/lib/types/components/backoffice/shared/BackofficeInlineFilterRow.d.ts.map +1 -1
  156. package/lib/types/components/backoffice/shared/backofficeFilterableCell.css.d.ts.map +1 -1
  157. package/lib/types/components/backoffice/technical/TechnicalIdentifierValue.d.ts.map +1 -1
  158. package/lib/types/components/backoffice/tools/BackofficeTools.stories.d.ts.map +1 -1
  159. package/lib/types/components/backoffice/tools/BackofficeToolsDocPanel.d.ts.map +1 -1
  160. package/lib/types/components/backoffice/tools/BackofficeToolsErrorFallback.d.ts.map +1 -1
  161. package/lib/types/components/backoffice/tools/BackofficeToolsJsonForm.d.ts.map +1 -1
  162. package/lib/types/components/backoffice/tools/BackofficeToolsQueryBoundary.d.ts.map +1 -1
  163. package/lib/types/hooks/useAuth.d.ts.map +1 -1
  164. package/lib/types/hooks/useBackofficeSessionAuth.d.ts.map +1 -1
  165. package/lib/types/hooks/useBackofficeSidebarPins.d.ts +6 -3
  166. package/lib/types/hooks/useBackofficeSidebarPins.d.ts.map +1 -1
  167. package/lib/types/hooks/useCopyToClipboard.d.ts.map +1 -1
  168. package/lib/types/hooks/useInfiniteConnection.d.ts.map +1 -1
  169. package/lib/types/hooks/useSidebarGroupCollapse.d.ts.map +1 -1
  170. package/lib/types/i18n/mergeResourceLanguages.d.ts +5 -2
  171. package/lib/types/i18n/mergeResourceLanguages.d.ts.map +1 -1
  172. package/lib/types/i18n/resources.d.ts.map +1 -1
  173. package/lib/types/modules/uploads.d.ts.map +1 -1
  174. package/lib/types/pages/BackofficeAcceptInvitationPage.d.ts.map +1 -1
  175. package/lib/types/pages/BackofficeDashboardPage.d.ts.map +1 -1
  176. package/lib/types/pages/BackofficeDashboardPage.helpers.d.ts.map +1 -1
  177. package/lib/types/pages/BackofficeDashboardPage.stories.d.ts.map +1 -1
  178. package/lib/types/pages/BackofficeDashboardShellPage.d.ts.map +1 -1
  179. package/lib/types/pages/BackofficeDashboardWidgetContent.d.ts.map +1 -1
  180. package/lib/types/pages/BackofficeEntityDetailFramePage.d.ts.map +1 -1
  181. package/lib/types/pages/BackofficeEntityDetailLayoutPage.d.ts.map +1 -1
  182. package/lib/types/pages/BackofficeEntityDetailPage.d.ts.map +1 -1
  183. package/lib/types/pages/BackofficeEntityDetailPage.helpers.d.ts.map +1 -1
  184. package/lib/types/pages/BackofficeEntityDetailPage.view-helpers.d.ts +1 -1
  185. package/lib/types/pages/BackofficeEntityDetailPage.view-helpers.d.ts.map +1 -1
  186. package/lib/types/pages/BackofficeEntityDetailPageConfigPage.d.ts.map +1 -1
  187. package/lib/types/pages/BackofficeEntityDetailShellPage.d.ts.map +1 -1
  188. package/lib/types/pages/BackofficeEntityDetailUnknownPageRedirect.d.ts.map +1 -1
  189. package/lib/types/pages/BackofficeEntityListDataPage.d.ts.map +1 -1
  190. package/lib/types/pages/BackofficeEntityListPage.d.ts.map +1 -1
  191. package/lib/types/pages/BackofficeEntityListPage.helpers.d.ts.map +1 -1
  192. package/lib/types/pages/BackofficeEntityListRouteContext.d.ts.map +1 -1
  193. package/lib/types/pages/BackofficeEntityListShellPage.d.ts.map +1 -1
  194. package/lib/types/pages/BackofficeHubPage.d.ts.map +1 -1
  195. package/lib/types/pages/BackofficeLayoutPage.d.ts.map +1 -1
  196. package/lib/types/pages/BackofficeLoginPage.d.ts.map +1 -1
  197. package/lib/types/pages/BackofficePasswordResetCompletePage.d.ts.map +1 -1
  198. package/lib/types/pages/BackofficePasswordResetRequestPage.d.ts.map +1 -1
  199. package/lib/types/pages/BackofficeRedirect.d.ts.map +1 -1
  200. package/lib/types/pages/BackofficeToolShellPage.d.ts.map +1 -1
  201. package/lib/types/pages/BackofficeVerifyEmailPage.d.ts.map +1 -1
  202. package/lib/types/pages/detail/BackofficeEntityDetailManifestFallback.d.ts.map +1 -1
  203. package/lib/types/pages/detail/buildTabsItems.d.ts.map +1 -1
  204. package/lib/types/pages/detail/pageResolution.d.ts.map +1 -1
  205. package/lib/types/provider/BackofficeConfigContext.d.ts.map +1 -1
  206. package/lib/types/provider/BackofficeListUiStateContext.d.ts +1 -1
  207. package/lib/types/provider/BackofficeListUiStateContext.d.ts.map +1 -1
  208. package/lib/types/provider/BackofficeProvider.d.ts.map +1 -1
  209. package/lib/types/provider/dashboardRegistrations.d.ts.map +1 -1
  210. package/lib/types/provider/entityRegistry.d.ts +6 -3
  211. package/lib/types/provider/entityRegistry.d.ts.map +1 -1
  212. package/lib/types/provider/lazyValue.d.ts.map +1 -1
  213. package/lib/types/provider/useBackofficeEntityLoader.d.ts +6 -3
  214. package/lib/types/provider/useBackofficeEntityLoader.d.ts.map +1 -1
  215. package/lib/types/provider/useBackofficeLazyValue.d.ts.map +1 -1
  216. package/lib/types/relay/createInlineReader.d.ts.map +1 -1
  217. package/lib/types/relay/envHelpers.d.ts +6 -3
  218. package/lib/types/relay/envHelpers.d.ts.map +1 -1
  219. package/lib/types/relay/identityView.d.ts.map +1 -1
  220. package/lib/types/relay/mutationResult.d.ts.map +1 -1
  221. package/lib/types/relay/typedRelayHooks.d.ts +1 -1
  222. package/lib/types/relay/typedRelayHooks.d.ts.map +1 -1
  223. package/lib/types/router/backofficeAuthPaths.d.ts.map +1 -1
  224. package/lib/types/router/createBackofficeRoutes.d.ts +28 -17
  225. package/lib/types/router/createBackofficeRoutes.d.ts.map +1 -1
  226. package/lib/types/storybook/relay/RelayStory.d.ts.map +1 -1
  227. package/lib/types/subscriptions/useCursorResumableSubscription.d.ts.map +1 -1
  228. package/package.json +21 -21
@@ -1 +1 @@
1
- {"version":3,"file":"sidebarUtils.js","names":[],"sources":["../../../../../src/components/backoffice/layout/sidebarUtils.ts"],"sourcesContent":["import type { TFunction } from 'i18next';\n\nimport type {\n BackofficeEntityManifestMap,\n I18nLabel,\n} from '@plumile/backoffice-core/types.js';\nimport type {\n BackofficeSidebarConfig,\n BackofficeIconComponent,\n BackofficeSidebarGroupConfig,\n BackofficeSidebarItemDescriptor,\n BackofficeSidebarItemConfig,\n BackofficeSidebarHubConfig,\n BackofficeSidebarHubGroupConfig,\n BackofficeResolvedSidebarHubConfig,\n} from '../../../provider/types.js';\n\nexport const resolveLabel = (label: I18nLabel, tApp: TFunction): string => {\n return label(tApp);\n};\n\nexport const isActivePath = (pathname: string, href: string): boolean => {\n if (pathname === href) {\n return true;\n }\n if (href !== '/' && pathname.startsWith(`${href}/`)) {\n return true;\n }\n return false;\n};\n\nexport const joinBackofficePath = (\n basePath: string,\n pathSegment: string,\n): string => {\n const normalizedBasePath = basePath.replace(/\\/+$/g, '');\n const normalizedPathSegment = pathSegment.replace(/^\\/+/g, '');\n if (normalizedBasePath === '') {\n return `/${normalizedPathSegment}`;\n }\n return `${normalizedBasePath}/${normalizedPathSegment}`;\n};\n\nexport const buildDefaultGroups = (\n entities: BackofficeEntityManifestMap,\n): Record<string, BackofficeSidebarGroupConfig> => {\n const entityIds = Object.keys(entities);\n\n return {\n main: {\n entities: entityIds,\n },\n };\n};\n\nexport const resolveSidebarGroups = (\n entities: BackofficeEntityManifestMap,\n sidebar: BackofficeSidebarConfig | undefined,\n): Record<string, BackofficeSidebarGroupConfig> => {\n return sidebar?.groups ?? buildDefaultGroups(entities);\n};\n\nexport type EntityGroupLookup = Map<\n string,\n {\n groupId: string;\n groupIcon?: BackofficeIconComponent;\n itemIcon?: BackofficeIconComponent;\n }\n>;\n\nexport const resolveItemDescriptor = (\n item: BackofficeSidebarItemConfig,\n): BackofficeSidebarItemDescriptor => {\n if (item.kind === 'dashboard') {\n return { kind: 'dashboard', id: item.id ?? 'dashboard' };\n }\n return { kind: item.kind, id: item.id };\n};\n\nexport const resolveGroupItems = <\n TManifest extends BackofficeEntityManifestMap = BackofficeEntityManifestMap,\n>(\n group: BackofficeSidebarGroupConfig<TManifest>,\n): readonly BackofficeSidebarItemConfig<TManifest>[] => {\n if (group.items != null) {\n return group.items;\n }\n return (group.entities?.map((entityId) => {\n return { kind: 'entity', id: entityId } as const;\n }) ?? []) as unknown as readonly BackofficeSidebarItemConfig<TManifest>[];\n};\n\nexport type BackofficeResolvedSidebarHubConfigFor<\n TManifest extends BackofficeEntityManifestMap = BackofficeEntityManifestMap,\n> = BackofficeSidebarHubConfig<TManifest> & {\n groups: readonly BackofficeSidebarHubGroupConfig<TManifest>[];\n};\n\nexport const resolveSidebarHubFor = <\n TManifest extends BackofficeEntityManifestMap = BackofficeEntityManifestMap,\n>(\n item: BackofficeSidebarHubConfig<TManifest>,\n sidebar: BackofficeSidebarConfig<TManifest> | undefined,\n): BackofficeResolvedSidebarHubConfigFor<TManifest> => {\n const registeredHub = sidebar?.hubs?.[item.id];\n return {\n ...registeredHub,\n ...item,\n groups: item.groups ?? registeredHub?.groups ?? [],\n };\n};\n\nexport const resolveSidebarHub = (\n item: BackofficeSidebarHubConfig,\n sidebar: BackofficeSidebarConfig | undefined,\n): BackofficeResolvedSidebarHubConfig => {\n return resolveSidebarHubFor(item, sidebar);\n};\n\nexport const resolveHubEntityIds = (\n hub: BackofficeResolvedSidebarHubConfig,\n): readonly string[] => {\n const output: string[] = [];\n const seen = new Set<string>();\n hub.groups.forEach((group) => {\n group.items.forEach((item) => {\n if (seen.has(item.id)) {\n return;\n }\n seen.add(item.id);\n output.push(item.id);\n });\n });\n return output;\n};\n\nexport type ResolvedSidebarHubEntry = {\n groupId: string | null;\n hub: BackofficeResolvedSidebarHubConfig;\n icon?: BackofficeIconComponent;\n};\n\nexport const resolveSidebarHubEntries = (\n groups: Record<string, BackofficeSidebarGroupConfig>,\n sidebar: BackofficeSidebarConfig | undefined,\n): readonly ResolvedSidebarHubEntry[] => {\n const output: ResolvedSidebarHubEntry[] = [];\n const seen = new Set<string>();\n\n Object.entries(groups).forEach(([groupId, group]) => {\n resolveGroupItems(group).forEach((item) => {\n if (item.kind !== 'hub' || seen.has(item.id)) {\n return;\n }\n seen.add(item.id);\n output.push({\n groupId,\n hub: resolveSidebarHub(item, sidebar),\n icon: item.icon ?? group.icon,\n });\n });\n });\n\n Object.values(sidebar?.hubs ?? {}).forEach((hub) => {\n if (seen.has(hub.id)) {\n return;\n }\n seen.add(hub.id);\n output.push({\n groupId: null,\n hub: resolveSidebarHub(hub, sidebar),\n icon: hub.icon,\n });\n });\n\n return output;\n};\n\nexport const resolveGroupEntityIds = (\n group: BackofficeSidebarGroupConfig,\n sidebar?: BackofficeSidebarConfig,\n): readonly string[] => {\n return resolveGroupItems(group).flatMap((item) => {\n if (item.kind === 'entity' || item.kind === 'tool') {\n return [item.id];\n }\n if (item.kind === 'hub') {\n return resolveHubEntityIds(resolveSidebarHub(item, sidebar));\n }\n return [];\n });\n};\n\nexport const buildEntityGroupLookup = (\n groups: Record<string, BackofficeSidebarGroupConfig>,\n sidebar?: BackofficeSidebarConfig,\n): EntityGroupLookup => {\n const lookup: EntityGroupLookup = new Map();\n\n Object.entries(groups).forEach(([groupId, group]) => {\n resolveGroupItems(group).forEach((item) => {\n if (item.kind === 'dashboard') {\n return;\n }\n\n if (item.kind === 'hub') {\n const hub = resolveSidebarHub(item, sidebar);\n resolveHubEntityIds(hub).forEach((entityId) => {\n if (!lookup.has(entityId)) {\n lookup.set(entityId, {\n groupId,\n groupIcon: group.icon,\n itemIcon: item.icon ?? hub.icon,\n });\n }\n });\n return;\n }\n\n if (!lookup.has(item.id)) {\n lookup.set(item.id, {\n groupId,\n groupIcon: group.icon,\n itemIcon: item.icon,\n });\n }\n });\n });\n\n return lookup;\n};\n\nconst isEntityVisible = (\n entityId: string,\n entities: BackofficeEntityManifestMap,\n sidebar: BackofficeSidebarConfig | undefined,\n permissions: unknown,\n): boolean => {\n const config = entities[entityId];\n if (config == null) {\n return false;\n }\n\n let descriptor: BackofficeSidebarItemDescriptor = {\n kind: 'entity',\n id: entityId,\n };\n if (config.kind === 'tool') {\n descriptor = { kind: 'tool', id: entityId };\n }\n\n if (sidebar?.isItemVisible != null) {\n return sidebar.isItemVisible(descriptor, permissions);\n }\n\n if (config.kind === 'tool') {\n return true;\n }\n return config.hasList;\n};\n\nexport const resolveVisibleEntityIds = (\n groups: Record<string, BackofficeSidebarGroupConfig>,\n entities: BackofficeEntityManifestMap,\n sidebar: BackofficeSidebarConfig | undefined,\n permissions: unknown,\n): string[] => {\n const output: string[] = [];\n const seen = new Set<string>();\n\n Object.entries(groups).forEach(([, group]) => {\n if (group.isVisible != null && !group.isVisible(permissions)) {\n return;\n }\n resolveGroupEntityIds(group, sidebar).forEach((entityId) => {\n if (seen.has(entityId)) {\n return;\n }\n if (!isEntityVisible(entityId, entities, sidebar, permissions)) {\n return;\n }\n seen.add(entityId);\n output.push(entityId);\n });\n });\n\n return output;\n};\n\nexport const resolveActiveEntityId = (\n pathname: string,\n entities: BackofficeEntityManifestMap,\n): string | null => {\n const entries = Object.entries(entities);\n for (const [entityId, config] of entries) {\n if (config.kind === 'tool') {\n if (isActivePath(pathname, config.routes.list)) {\n return entityId;\n }\n } else if (config.hasList && isActivePath(pathname, config.routes.list)) {\n return entityId;\n }\n }\n return null;\n};\n\nexport const resolveActiveGroupId = (\n groups: Record<string, BackofficeSidebarGroupConfig>,\n activeEntityId: string | null,\n entities: BackofficeEntityManifestMap,\n sidebar: BackofficeSidebarConfig | undefined,\n permissions: unknown,\n): string | null => {\n if (activeEntityId == null) {\n return null;\n }\n\n if (!isEntityVisible(activeEntityId, entities, sidebar, permissions)) {\n return null;\n }\n\n for (const [groupId, group] of Object.entries(groups)) {\n const isVisible = group.isVisible == null || group.isVisible(permissions);\n if (\n isVisible &&\n resolveGroupEntityIds(group, sidebar).includes(activeEntityId)\n ) {\n return groupId;\n }\n }\n\n return null;\n};\n"],"mappings":";AAiBA,IAAa,KAAgB,GAAkB,MACtC,EAAM,CAAI,GAGN,KAAgB,GAAkB,MAI7C,GAHI,MAAa,KAGb,MAAS,OAAO,EAAS,WAAW,GAAG,EAAK,EAAE,IAMvC,KACX,GACA,MACW;CACX,IAAM,IAAqB,EAAS,QAAQ,SAAS,EAAE,GACjD,IAAwB,EAAY,QAAQ,SAAS,EAAE;CAI7D,OAHI,MAAuB,KAClB,IAAI,MAEN,GAAG,EAAmB,GAAG;AAClC,GAEa,KACX,OAIO,EACL,MAAM,EACJ,UAJc,OAAO,KAAK,CAIhB,EACZ,EACF,IAGW,KACX,GACA,MAEO,GAAS,UAAU,EAAmB,CAAQ,GAY1C,KACX,MAEI,EAAK,SAAS,cACT;CAAE,MAAM;CAAa,IAAI,EAAK,MAAM;AAAY,IAElD;CAAE,MAAM,EAAK;CAAM,IAAI,EAAK;AAAG,GAG3B,KAGX,MAEI,EAAM,SAAS,OAGX,EAAM,UAAU,KAAK,OACpB;CAAE,MAAM;CAAU,IAAI;AAAS,EACvC,KAAK,CAAC,IAJE,EAAM,OAaJ,KAGX,GACA,MACqD;CACrD,IAAM,IAAgB,GAAS,OAAO,EAAK;CAC3C,OAAO;EACL,GAAG;EACH,GAAG;EACH,QAAQ,EAAK,UAAU,GAAe,UAAU,CAAC;CACnD;AACF,GAEa,KACX,GACA,MAEO,EAAqB,GAAM,CAAO,GAG9B,KACX,MACsB;CACtB,IAAM,IAAmB,CAAC,GACpB,oBAAO,IAAI,IAAY;CAU7B,OATA,EAAI,OAAO,SAAS,MAAU;EAC5B,EAAM,MAAM,SAAS,MAAS;GACxB,EAAK,IAAI,EAAK,EAAE,MAGpB,EAAK,IAAI,EAAK,EAAE,GAChB,EAAO,KAAK,EAAK,EAAE;EACrB,CAAC;CACH,CAAC,GACM;AACT,GAQa,KACX,GACA,MACuC;CACvC,IAAM,IAAoC,CAAC,GACrC,oBAAO,IAAI,IAAY;CA4B7B,OA1BA,OAAO,QAAQ,CAAM,CAAC,CAAC,SAAS,CAAC,GAAS,OAAW;EACnD,EAAkB,CAAK,CAAC,CAAC,SAAS,MAAS;GACrC,EAAK,SAAS,SAAS,EAAK,IAAI,EAAK,EAAE,MAG3C,EAAK,IAAI,EAAK,EAAE,GAChB,EAAO,KAAK;IACV;IACA,KAAK,EAAkB,GAAM,CAAO;IACpC,MAAM,EAAK,QAAQ,EAAM;GAC3B,CAAC;EACH,CAAC;CACH,CAAC,GAED,OAAO,OAAO,GAAS,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,MAAQ;EAC9C,EAAK,IAAI,EAAI,EAAE,MAGnB,EAAK,IAAI,EAAI,EAAE,GACf,EAAO,KAAK;GACV,SAAS;GACT,KAAK,EAAkB,GAAK,CAAO;GACnC,MAAM,EAAI;EACZ,CAAC;CACH,CAAC,GAEM;AACT,GAEa,KACX,GACA,MAEO,EAAkB,CAAK,CAAC,CAAC,SAAS,MACnC,EAAK,SAAS,YAAY,EAAK,SAAS,SACnC,CAAC,EAAK,EAAE,IAEb,EAAK,SAAS,QACT,EAAoB,EAAkB,GAAM,CAAO,CAAC,IAEtD,CAAC,CACT,GAGU,KACX,GACA,MACsB;CACtB,IAAM,oBAA4B,IAAI,IAAI;CAgC1C,OA9BA,OAAO,QAAQ,CAAM,CAAC,CAAC,SAAS,CAAC,GAAS,OAAW;EACnD,EAAkB,CAAK,CAAC,CAAC,SAAS,MAAS;GACrC,MAAK,SAAS,aAIlB;QAAI,EAAK,SAAS,OAAO;KACvB,IAAM,IAAM,EAAkB,GAAM,CAAO;KAC3C,EAAoB,CAAG,CAAC,CAAC,SAAS,MAAa;MAC7C,AAAK,EAAO,IAAI,CAAQ,KACtB,EAAO,IAAI,GAAU;OACnB;OACA,WAAW,EAAM;OACjB,UAAU,EAAK,QAAQ,EAAI;MAC7B,CAAC;KAEL,CAAC;KACD;IACF;IAEA,AAAK,EAAO,IAAI,EAAK,EAAE,KACrB,EAAO,IAAI,EAAK,IAAI;KAClB;KACA,WAAW,EAAM;KACjB,UAAU,EAAK;IACjB,CAAC;GAPH;EASF,CAAC;CACH,CAAC,GAEM;AACT,GAEM,KACJ,GACA,GACA,GACA,MACY;CACZ,IAAM,IAAS,EAAS;CACxB,IAAI,KAAU,MACZ,OAAO;CAGT,IAAI,IAA8C;EAChD,MAAM;EACN,IAAI;CACN;CAYA,OAXI,EAAO,SAAS,WAClB,IAAa;EAAE,MAAM;EAAQ,IAAI;CAAS,IAGxC,GAAS,iBAAiB,OAI1B,EAAO,SAAS,SACX,KAEF,EAAO,UANL,EAAQ,cAAc,GAAY,CAAW;AAOxD,GAEa,KACX,GACA,GACA,GACA,MACa;CACb,IAAM,IAAmB,CAAC,GACpB,oBAAO,IAAI,IAAY;CAkB7B,OAhBA,OAAO,QAAQ,CAAM,CAAC,CAAC,SAAS,GAAG,OAAW;EACxC,EAAM,aAAa,QAAQ,CAAC,EAAM,UAAU,CAAW,KAG3D,EAAsB,GAAO,CAAO,CAAC,CAAC,SAAS,MAAa;GACtD,EAAK,IAAI,CAAQ,KAGhB,EAAgB,GAAU,GAAU,GAAS,CAAW,MAG7D,EAAK,IAAI,CAAQ,GACjB,EAAO,KAAK,CAAQ;EACtB,CAAC;CACH,CAAC,GAEM;AACT,GAEa,KACX,GACA,MACkB;CAClB,IAAM,IAAU,OAAO,QAAQ,CAAQ;CACvC,KAAK,IAAM,CAAC,GAAU,MAAW,GAC/B,IAAI,EAAO,SAAS;MACd,EAAa,GAAU,EAAO,OAAO,IAAI,GAC3C,OAAO;CAAA,OAEJ,IAAI,EAAO,WAAW,EAAa,GAAU,EAAO,OAAO,IAAI,GACpE,OAAO;CAGX,OAAO;AACT,GAEa,KACX,GACA,GACA,GACA,GACA,MACkB;CAKlB,IAJI,KAAkB,QAIlB,CAAC,EAAgB,GAAgB,GAAU,GAAS,CAAW,GACjE,OAAO;CAGT,KAAK,IAAM,CAAC,GAAS,MAAU,OAAO,QAAQ,CAAM,GAElD,KADkB,EAAM,aAAa,QAAQ,EAAM,UAAU,CAAW,MAGtE,EAAsB,GAAO,CAAO,CAAC,CAAC,SAAS,CAAc,GAE7D,OAAO;CAIX,OAAO;AACT"}
1
+ {"version":3,"file":"sidebarUtils.js","names":[],"sources":["../../../../../src/components/backoffice/layout/sidebarUtils.ts"],"sourcesContent":["import type { TFunction } from 'i18next';\n\nimport type {\n BackofficeEntityManifestMap,\n I18nLabel,\n} from '@plumile/backoffice-core/types.js';\nimport type {\n BackofficeSidebarConfig,\n BackofficeIconComponent,\n BackofficeSidebarGroupConfig,\n BackofficeSidebarItemDescriptor,\n BackofficeSidebarItemConfig,\n BackofficeSidebarHubConfig,\n BackofficeSidebarHubGroupConfig,\n BackofficeResolvedSidebarHubConfig,\n} from '../../../provider/types.js';\n\nexport const resolveLabel = (label: I18nLabel, tApp: TFunction): string => {\n return label(tApp);\n};\n\nexport const isActivePath = (pathname: string, href: string): boolean => {\n if (pathname === href) {\n return true;\n }\n if (href !== '/' && pathname.startsWith(`${href}/`)) {\n return true;\n }\n return false;\n};\n\nexport const joinBackofficePath = (\n basePath: string,\n pathSegment: string,\n): string => {\n const normalizedBasePath = basePath.replace(/\\/+$/g, '');\n const normalizedPathSegment = pathSegment.replace(/^\\/+/g, '');\n if (normalizedBasePath === '') {\n return `/${normalizedPathSegment}`;\n }\n return `${normalizedBasePath}/${normalizedPathSegment}`;\n};\n\nexport const buildDefaultGroups = (\n entities: BackofficeEntityManifestMap,\n): Record<string, BackofficeSidebarGroupConfig> => {\n const entityIds = Object.keys(entities);\n\n return {\n main: {\n entities: entityIds,\n },\n };\n};\n\nexport const resolveSidebarGroups = (\n entities: BackofficeEntityManifestMap,\n sidebar: BackofficeSidebarConfig | undefined,\n): Record<string, BackofficeSidebarGroupConfig> => {\n return sidebar?.groups ?? buildDefaultGroups(entities);\n};\n\nexport type EntityGroupLookup = Map<\n string,\n {\n groupId: string;\n groupIcon?: BackofficeIconComponent;\n itemIcon?: BackofficeIconComponent;\n }\n>;\n\nexport const resolveItemDescriptor = (\n item: BackofficeSidebarItemConfig,\n): BackofficeSidebarItemDescriptor => {\n if (item.kind === 'dashboard') {\n return { kind: 'dashboard', id: item.id ?? 'dashboard' };\n }\n return { kind: item.kind, id: item.id };\n};\n\nexport const resolveGroupItems = <\n TManifest extends BackofficeEntityManifestMap = BackofficeEntityManifestMap,\n>(\n group: BackofficeSidebarGroupConfig<TManifest>,\n): readonly BackofficeSidebarItemConfig<TManifest>[] => {\n if (group.items != null) {\n return group.items;\n }\n return (group.entities?.map((entityId) => {\n return { kind: 'entity', id: entityId } as const;\n }) ?? []) as unknown as readonly BackofficeSidebarItemConfig<TManifest>[];\n};\n\nexport type BackofficeResolvedSidebarHubConfigFor<\n TManifest extends BackofficeEntityManifestMap = BackofficeEntityManifestMap,\n> = BackofficeSidebarHubConfig<TManifest> & {\n groups: readonly BackofficeSidebarHubGroupConfig<TManifest>[];\n};\n\nexport const resolveSidebarHubFor = <\n TManifest extends BackofficeEntityManifestMap = BackofficeEntityManifestMap,\n>(\n item: BackofficeSidebarHubConfig<TManifest>,\n sidebar: BackofficeSidebarConfig<TManifest> | undefined,\n): BackofficeResolvedSidebarHubConfigFor<TManifest> => {\n const registeredHub = sidebar?.hubs?.[item.id];\n return {\n ...registeredHub,\n ...item,\n groups: item.groups ?? registeredHub?.groups ?? [],\n };\n};\n\nexport const resolveSidebarHub = (\n item: BackofficeSidebarHubConfig,\n sidebar: BackofficeSidebarConfig | undefined,\n): BackofficeResolvedSidebarHubConfig => {\n return resolveSidebarHubFor(item, sidebar);\n};\n\nexport const resolveHubEntityIds = (\n hub: BackofficeResolvedSidebarHubConfig,\n): readonly string[] => {\n const output: string[] = [];\n const seen = new Set<string>();\n hub.groups.forEach((group) => {\n group.items.forEach((item) => {\n if (seen.has(item.id)) {\n return;\n }\n seen.add(item.id);\n output.push(item.id);\n });\n });\n return output;\n};\n\nexport type ResolvedSidebarHubEntry = {\n groupId: string | null;\n hub: BackofficeResolvedSidebarHubConfig;\n icon?: BackofficeIconComponent;\n};\n\nexport const resolveSidebarHubEntries = (\n groups: Record<string, BackofficeSidebarGroupConfig>,\n sidebar: BackofficeSidebarConfig | undefined,\n): readonly ResolvedSidebarHubEntry[] => {\n const output: ResolvedSidebarHubEntry[] = [];\n const seen = new Set<string>();\n\n Object.entries(groups).forEach(([groupId, group]) => {\n resolveGroupItems(group).forEach((item) => {\n if (item.kind !== 'hub' || seen.has(item.id)) {\n return;\n }\n seen.add(item.id);\n output.push({\n groupId,\n hub: resolveSidebarHub(item, sidebar),\n icon: item.icon ?? group.icon,\n });\n });\n });\n\n Object.values(sidebar?.hubs ?? {}).forEach((hub) => {\n if (seen.has(hub.id)) {\n return;\n }\n seen.add(hub.id);\n output.push({\n groupId: null,\n hub: resolveSidebarHub(hub, sidebar),\n icon: hub.icon,\n });\n });\n\n return output;\n};\n\nexport const resolveGroupEntityIds = (\n group: BackofficeSidebarGroupConfig,\n sidebar?: BackofficeSidebarConfig,\n): readonly string[] => {\n return resolveGroupItems(group).flatMap((item) => {\n if (item.kind === 'entity' || item.kind === 'tool') {\n return [item.id];\n }\n if (item.kind === 'hub') {\n return resolveHubEntityIds(resolveSidebarHub(item, sidebar));\n }\n return [];\n });\n};\n\nexport const buildEntityGroupLookup = (\n groups: Record<string, BackofficeSidebarGroupConfig>,\n sidebar?: BackofficeSidebarConfig,\n): EntityGroupLookup => {\n const lookup: EntityGroupLookup = new Map();\n\n Object.entries(groups).forEach(([groupId, group]) => {\n resolveGroupItems(group).forEach((item) => {\n if (item.kind === 'dashboard') {\n return;\n }\n\n if (item.kind === 'hub') {\n const hub = resolveSidebarHub(item, sidebar);\n resolveHubEntityIds(hub).forEach((entityId) => {\n if (!lookup.has(entityId)) {\n lookup.set(entityId, {\n groupId,\n groupIcon: group.icon,\n itemIcon: item.icon ?? hub.icon,\n });\n }\n });\n return;\n }\n\n if (!lookup.has(item.id)) {\n lookup.set(item.id, {\n groupId,\n groupIcon: group.icon,\n itemIcon: item.icon,\n });\n }\n });\n });\n\n return lookup;\n};\n\nconst isEntityVisible = (\n entityId: string,\n entities: BackofficeEntityManifestMap,\n sidebar: BackofficeSidebarConfig | undefined,\n permissions: unknown,\n): boolean => {\n const config = entities[entityId];\n if (config == null) {\n return false;\n }\n\n let descriptor: BackofficeSidebarItemDescriptor = {\n kind: 'entity',\n id: entityId,\n };\n if (config.kind === 'tool') {\n descriptor = { kind: 'tool', id: entityId };\n }\n\n if (sidebar?.isItemVisible != null) {\n return sidebar.isItemVisible(descriptor, permissions);\n }\n\n if (config.kind === 'tool') {\n return true;\n }\n return config.hasList;\n};\n\nexport const resolveVisibleEntityIds = (\n groups: Record<string, BackofficeSidebarGroupConfig>,\n entities: BackofficeEntityManifestMap,\n sidebar: BackofficeSidebarConfig | undefined,\n permissions: unknown,\n): string[] => {\n const output: string[] = [];\n const seen = new Set<string>();\n\n Object.entries(groups).forEach(([, group]) => {\n if (group.isVisible != null && !group.isVisible(permissions)) {\n return;\n }\n resolveGroupEntityIds(group, sidebar).forEach((entityId) => {\n if (seen.has(entityId)) {\n return;\n }\n if (!isEntityVisible(entityId, entities, sidebar, permissions)) {\n return;\n }\n seen.add(entityId);\n output.push(entityId);\n });\n });\n\n return output;\n};\n\nexport const resolveActiveEntityId = (\n pathname: string,\n entities: BackofficeEntityManifestMap,\n): string | null => {\n const entries = Object.entries(entities);\n for (const [entityId, config] of entries) {\n if (config.kind === 'tool') {\n if (isActivePath(pathname, config.routes.list)) {\n return entityId;\n }\n } else if (config.hasList && isActivePath(pathname, config.routes.list)) {\n return entityId;\n }\n }\n return null;\n};\n\nexport const resolveActiveGroupId = (\n groups: Record<string, BackofficeSidebarGroupConfig>,\n activeEntityId: string | null,\n entities: BackofficeEntityManifestMap,\n sidebar: BackofficeSidebarConfig | undefined,\n permissions: unknown,\n): string | null => {\n if (activeEntityId == null) {\n return null;\n }\n\n if (!isEntityVisible(activeEntityId, entities, sidebar, permissions)) {\n return null;\n }\n\n for (const [groupId, group] of Object.entries(groups)) {\n const isVisible = group.isVisible == null || group.isVisible(permissions);\n if (\n isVisible &&\n resolveGroupEntityIds(group, sidebar).includes(activeEntityId)\n ) {\n return groupId;\n }\n }\n\n return null;\n};\n"],"mappings":"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"}
@@ -1,4 +1,3 @@
1
- /* empty css */
2
1
  //#region src/components/backoffice/links/backofficeLink.css.ts
3
2
  var e = "txvbqbfqq txvbqbey txvbqbhd8", t = "txvbqbfqq txvbqbey txvbqbls4 txvbqb1bd1 txvbqbfwv txvbqb1ac4 txvbqbkh6", n = "txvbqbv7x";
4
3
  //#endregion
@@ -1,4 +1,3 @@
1
- /* empty css */
2
1
  //#region src/components/backoffice/list/RowFlagsCell.css.ts
3
2
  var e = "txvbqb10mk txvbqb11k5 txvbqb12hd txvbqbxtg txvbqbls4", t = "txvbqbfqq txvbqbey txvbqbls4 txvbqbi8n txvbqb19us", n = "qbwcuex qbwcuer txvbqbfqq txvbqbey txvbqbls4 txvbqbh6d txvbqbo4m qbwcue11 qbwcuev txvbqb19hf txvbqbjmh txvbqbvat txvbqbub2";
4
3
  //#endregion
@@ -1,4 +1,3 @@
1
- /* empty css */
2
1
  //#region src/components/backoffice/pickers/entityIdPickerDialog.css.ts
3
2
  var e = "txvbqb10m7 txvbqb11js txvbqb12ig txvbqbxuj txvbqb1bgt txvbqb9j txvbqb18e2", t = "txvbqb10na txvbqb11kv txvbqb12it txvbqbxuw txvbqbfpn txvbqbey txvbqbls4 txvbqbhdl txvbqb1bgt", n = "txvbqb9j txvbqb1bgt";
4
3
  //#endregion
@@ -1,4 +1,3 @@
1
- /* empty css */
2
1
  //#region src/components/backoffice/refs/backofficeEntityIdRef.css.ts
3
2
  var e = "qbwcuep qbwcuen txvbqbfqq txvbqbey txvbqbhd8 txvbqb1bgr txvbqb3f txvbqb7h txvbqb75 txvbqb7t qbwcueo txvbqb1gdj qbwcue0 txvbqb1fgi txvbqb1gaq";
4
3
  //#endregion
@@ -1,4 +1,3 @@
1
- /* empty css */
2
1
  //#region src/components/backoffice/routing/backofficeContentBoundary.css.ts
3
2
  var e = "txvbqbfpn txvbqbh4x txvbqbuo2 txvbqb19us txvbqbv7x";
4
3
  //#endregion
@@ -1,4 +1,3 @@
1
- /* empty css */
2
1
  //#region src/components/backoffice/routing/backofficeContentError.css.ts
3
2
  var e = "txvbqbfpn txvbqbh4x txvbqb19us", t = "txvbqb1dm";
4
3
  //#endregion
@@ -1,4 +1,3 @@
1
- /* empty css */
2
1
  //#region src/components/backoffice/routing/backofficeContentFallback.css.ts
3
2
  var e = "txvbqbfpn txvbqbh4x txvbqbheb txvbqb19us txvbqbuo2", t = "txvbqbu5n", n = "txvbqbfq0 txvbqbheb txvbqbjdt", r = "txvbqbfpn txvbqbh4x txvbqbhdy txvbqbwxb txvbqbuhx txvbqb2up txvbqb28o txvbqb2sj txvbqb1d9 txvbqb1b8t";
4
3
  //#endregion
@@ -1,4 +1,3 @@
1
- /* empty css */
2
1
  //#region src/components/backoffice/routing/backofficeRouteFallback.css.ts
3
2
  var e = "txvbqbfpn txvbqbh4x txvbqbey txvbqbls4 txvbqbv7k txvbqb19us txvbqbheb txvbqb1b8r txvbqb1bgt", t = "txvbqb1bgv";
4
3
  //#endregion
@@ -140,8 +140,8 @@ var S = (e, t) => e(t), Te = (e, t) => e.fromGraphQL != null && t != null ? e.fr
140
140
  typeof r == "string" && (i = r), typeof r == "number" && Number.isFinite(r) && (i = String(r));
141
141
  let s = S(e.label, C);
142
142
  if (e.kind === "text") {
143
- let t = w("filters.placeholders.search", { label: e.placeholderLabel == null ? s : S(e.placeholderLabel, C) });
144
- return e.placeholderText != null && (t = S(e.placeholderText, C)), /* @__PURE__ */ g(a, {
143
+ let t = e.placeholderLabel == null ? s : S(e.placeholderLabel, C), r = w("filters.placeholders.search", { label: t });
144
+ return e.placeholderText != null && (r = S(e.placeholderText, C)), /* @__PURE__ */ g(a, {
145
145
  value: i,
146
146
  onApply: (t) => {
147
147
  let r = x(E.where, n, t, e.path);
@@ -150,14 +150,14 @@ var S = (e, t) => e(t), Te = (e, t) => e.fromGraphQL != null && t != null ? e.fr
150
150
  where: r
151
151
  });
152
152
  },
153
- placeholder: t,
154
- ariaLabel: t,
153
+ placeholder: r,
154
+ ariaLabel: r,
155
155
  className: d
156
156
  });
157
157
  }
158
158
  if (e.kind === "datetime") {
159
- let t = w("filters.placeholders.search", { label: e.placeholderLabel == null ? s : S(e.placeholderLabel, C) });
160
- return e.placeholderText != null && (t = S(e.placeholderText, C)), /* @__PURE__ */ g(a, {
159
+ let t = e.placeholderLabel == null ? s : S(e.placeholderLabel, C), r = w("filters.placeholders.search", { label: t });
160
+ return e.placeholderText != null && (r = S(e.placeholderText, C)), /* @__PURE__ */ g(a, {
161
161
  value: Oe(i),
162
162
  onApply: (t) => {
163
163
  let r = ke(t), i = x(E.where, n, r, e.path);
@@ -166,15 +166,15 @@ var S = (e, t) => e(t), Te = (e, t) => e.fromGraphQL != null && t != null ? e.fr
166
166
  where: i
167
167
  });
168
168
  },
169
- placeholder: t,
170
- ariaLabel: t,
169
+ placeholder: r,
170
+ ariaLabel: r,
171
171
  className: d,
172
172
  type: "datetime-local"
173
173
  });
174
174
  }
175
175
  if (e.kind === "number") {
176
- let t = w("filters.placeholders.search", { label: e.placeholderLabel == null ? s : S(e.placeholderLabel, C) });
177
- return e.placeholderText != null && (t = S(e.placeholderText, C)), /* @__PURE__ */ g(a, {
176
+ let t = e.placeholderLabel == null ? s : S(e.placeholderLabel, C), r = w("filters.placeholders.search", { label: t });
177
+ return e.placeholderText != null && (r = S(e.placeholderText, C)), /* @__PURE__ */ g(a, {
178
178
  value: i,
179
179
  onApply: (t) => {
180
180
  let r = t.trim(), i = r === "" ? null : Number(r), a = x(E.where, n, Number.isFinite(i) ? i : null, e.path);
@@ -183,8 +183,8 @@ var S = (e, t) => e(t), Te = (e, t) => e.fromGraphQL != null && t != null ? e.fr
183
183
  where: a
184
184
  });
185
185
  },
186
- placeholder: t,
187
- ariaLabel: t,
186
+ placeholder: r,
187
+ ariaLabel: r,
188
188
  className: d,
189
189
  inputMode: e.inputMode ?? "numeric",
190
190
  type: "text"
@@ -301,8 +301,8 @@ var S = (e, t) => e(t), Te = (e, t) => e.fromGraphQL != null && t != null ? e.fr
301
301
  });
302
302
  }
303
303
  if (e.kind === "stringList") {
304
- let t = w("filters.placeholders.search", { label: e.placeholderLabel == null ? s : S(e.placeholderLabel, C) });
305
- return e.placeholderText != null && (t = S(e.placeholderText, C)), /* @__PURE__ */ g(a, {
304
+ let t = e.placeholderLabel == null ? s : S(e.placeholderLabel, C), r = w("filters.placeholders.search", { label: t });
305
+ return e.placeholderText != null && (r = S(e.placeholderText, C)), /* @__PURE__ */ g(a, {
306
306
  value: i,
307
307
  onApply: (t) => {
308
308
  let r = t.split(/[\n,]+/u).map((e) => e.trim()).filter((e) => e !== ""), i = x(E.where, n, r, e.path);
@@ -311,8 +311,8 @@ var S = (e, t) => e(t), Te = (e, t) => e.fromGraphQL != null && t != null ? e.fr
311
311
  where: i
312
312
  });
313
313
  },
314
- placeholder: t,
315
- ariaLabel: t,
314
+ placeholder: r,
315
+ ariaLabel: r,
316
316
  className: d
317
317
  });
318
318
  }
@@ -366,7 +366,7 @@ var S = (e, t) => e(t), Te = (e, t) => e.fromGraphQL != null && t != null ? e.fr
366
366
  R.filters,
367
367
  R.ui?.toolbar,
368
368
  Ke
369
- ]), Y = p(() => R.filters.filter((e) => e.placement == null ? !0 : e.placement === "drawer" || e.placement === "both"), [R.filters]), X = p(() => J.find((e) => e.kind === "text"), [J]), qe = p(() => {
369
+ ]), Y = p(() => R.filters.filter((e) => e.placement == null || e.placement === "drawer" || e.placement === "both"), [R.filters]), X = p(() => J.find((e) => e.kind === "text"), [J]), qe = p(() => {
370
370
  let e = J.filter((e) => e !== X);
371
371
  return e.length === 0 ? null : /* @__PURE__ */ g("div", {
372
372
  className: u,
@@ -1 +1 @@
1
- {"version":3,"file":"BackofficeEntityListScaffold.js","names":[],"sources":["../../../../../src/components/backoffice/scaffolds/BackofficeEntityListScaffold.tsx"],"sourcesContent":["/* eslint-disable no-ternary */\nimport {\n type JSX,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport type { TFunction } from 'i18next';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@plumile/ui/atomic/atoms/button/Button.js';\nimport { BackofficeEmptyState } from '@plumile/ui/backoffice/molecules/backoffice_empty_state/BackofficeEmptyState.js';\nimport { BackofficeFilterDrawer } from '@plumile/ui/backoffice/molecules/backoffice_filter_drawer/BackofficeFilterDrawer.js';\nimport { BackofficeFilterField } from '@plumile/ui/backoffice/molecules/backoffice_filter_field/BackofficeFilterField.js';\nimport { Spinner } from '@plumile/ui/backoffice/atoms/spinner/Spinner.js';\nimport { Tag } from '@plumile/ui/backoffice/atoms/tag/Tag.js';\nimport { BackofficeListFooter } from '@plumile/ui/backoffice/molecules/backoffice_list_footer/BackofficeListFooter.js';\nimport { BackofficePageHeader } from '@plumile/ui/backoffice/molecules/backoffice_page_header/BackofficePageHeader.js';\nimport { BackofficeToolbar } from '@plumile/ui/backoffice/molecules/backoffice_toolbar/BackofficeToolbar.js';\nimport { BackofficeTableSkeleton } from '@plumile/ui/backoffice/molecules/backoffice_table_skeleton/BackofficeTableSkeleton.js';\nimport {\n FilterChipRow,\n type FilterChip,\n} from '@plumile/ui/backoffice/molecules/filter_chip_row/FilterChipRow.js';\nimport { InlineBanner } from '@plumile/ui/components/feedback/InlineBanner.js';\nimport { ListPageTemplate } from '@plumile/ui/backoffice/templates/list_page_template/ListPageTemplate.js';\nimport {\n type DataTableColumn,\n type GetRowId,\n} from '@plumile/ui/components/data-table/DataTable.js';\nimport { ResponsiveRecordList } from '@plumile/ui/components/data-table/ResponsiveRecordList.js';\nimport { VirtualizedConnectionTable } from '@plumile/ui/components/data-table/VirtualizedConnectionTable.js';\nimport { SimpleSelect } from '@plumile/ui/components/select/SimpleSelect.js';\nimport { denseTableClass } from '@plumile/ui/shared/backofficeTableDensity.css.js';\n\nimport {\n readWhereValue,\n setWhereValue,\n} from '@plumile/backoffice-core/filters/where.js';\nimport { resolveBackofficeListRuntimeConfig } from '@plumile/backoffice-core/config/listRuntime.js';\nimport type {\n BackofficeFilterSpec,\n BackofficeListState,\n BackofficePickerScope,\n BackofficeRuntimeResolvedListFacetConfig,\n I18nLabel,\n} from '@plumile/backoffice-core/types.js';\n\nimport { BackofficeErrorBoundary } from '../errors/BackofficeErrorBoundary.js';\nimport {\n EntityFilterValue,\n EntityFilterValueText,\n} from '../filters/EntityFilterValue.js';\nimport { EntityIdPickerDialog } from '../pickers/EntityIdPickerDialog.js';\nimport { EntityIdFilterField } from '../filters/EntityIdFilterField.js';\nimport { DeferredFilterSearchInput } from '../filters/DeferredFilterSearchInput.js';\nimport { BackofficeListFilterProvider } from './BackofficeListFilterContext.js';\nimport { BACKOFFICE_LIST_BODY_SCROLL_MODE } from './backofficeListScrollMode.js';\nimport { useBackofficeReactTranslation } from '../../../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeInfiniteScrollSentinel } from '../../../hooks/useBackofficeInfiniteScrollSentinel.js';\nimport type { BackofficeFilterDrawerState } from '../../../provider/BackofficeListUiStateContext.js';\nimport { isDevEnv } from '../../../relay/envHelpers.js';\n\nimport * as styles from './backofficeEntityListScaffold.css.js';\n\nconst resolveLabel = (label: I18nLabel, tApp: TFunction): string => {\n return label(tApp);\n};\n\nconst getFilterValue = <Where extends Record<string, unknown>>(\n filter: BackofficeFilterSpec<Where>,\n where: Where | null,\n): unknown => {\n if (filter.fromGraphQL != null && where != null) {\n return filter.fromGraphQL(where);\n }\n\n const key = (filter.whereKey ?? filter.id) as keyof Where;\n return readWhereValue(where, key, filter.path);\n};\n\nconst normalizeStringArray = (value: unknown): readonly string[] => {\n if (!Array.isArray(value)) {\n return [];\n }\n return value\n .map((entry) => {\n if (entry == null) {\n return null;\n }\n const normalized = String(entry).trim();\n if (normalized === '') {\n return null;\n }\n return normalized;\n })\n .filter((entry): entry is string => {\n return entry != null;\n });\n};\n\nconst getFilterDisplayValue = <Where extends Record<string, unknown>>(\n filter: BackofficeFilterSpec<Where>,\n raw: unknown,\n options: {\n enumLabel: (value: string) => string;\n booleanLabel: (value: boolean) => string;\n fallbackBooleanLabels: { yes: string; no: string };\n },\n): ReactNode | null => {\n if (raw == null) {\n return null;\n }\n\n if (Array.isArray(raw)) {\n const normalized = normalizeStringArray(raw);\n\n if (normalized.length === 0) {\n return null;\n }\n\n if (filter.kind === 'entityIdList') {\n return (\n <>\n {normalized.map((id, index) => {\n return (\n <span key={id}>\n <EntityFilterValue entityId={filter.entity} id={id} />\n {index < normalized.length - 1 ? ', ' : null}\n </span>\n );\n })}\n </>\n );\n }\n\n return normalized.join(', ');\n }\n\n if (typeof raw === 'boolean') {\n if (filter.kind === 'boolean') {\n return options.booleanLabel(raw);\n }\n if (raw) {\n return options.fallbackBooleanLabels.yes;\n }\n return options.fallbackBooleanLabels.no;\n }\n\n if (typeof raw !== 'string' && typeof raw !== 'number') {\n return null;\n }\n\n const rawString = String(raw).trim();\n if (rawString === '') {\n return null;\n }\n\n if (filter.kind === 'entityId') {\n return <EntityFilterValue entityId={filter.entity} id={rawString} />;\n }\n\n if (filter.kind === 'enum') {\n return options.enumLabel(rawString);\n }\n\n return rawString;\n};\n\nconst toDatetimeInputValue = (value: string): string => {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) {\n return value;\n }\n const offsetMs = date.getTimezoneOffset() * 60_000;\n return new Date(date.getTime() - offsetMs).toISOString().slice(0, 16);\n};\n\nconst fromDatetimeInputValue = (value: string): string => {\n const normalized = value.trim();\n if (normalized === '') {\n return '';\n }\n const date = new Date(normalized);\n if (Number.isNaN(date.getTime())) {\n return normalized;\n }\n return date.toISOString();\n};\n\ntype RuntimeWhere = Record<string, unknown>;\ntype RuntimeSort = string;\n\ntype Props<RowView> = {\n config: BackofficeRuntimeResolvedListFacetConfig;\n state: BackofficeListState<RuntimeWhere, RuntimeSort>;\n pushState: (next: BackofficeListState<RuntimeWhere, RuntimeSort>) => void;\n header?: {\n title?: string;\n subtitle?: string;\n };\n headerActions?: ReactNode;\n rows: readonly RowView[];\n getRowId: GetRowId<RowView>;\n columns: readonly DataTableColumn<RowView>[];\n gridTemplateColumns?: string;\n hasNextPage: boolean;\n isLoadingMore: boolean;\n isRefreshing?: boolean;\n onLoadMore: () => void;\n onRefresh?: () => void;\n totalCount?: number | null;\n loadedCountLabel?: ReactNode;\n emptyState?: JSX.Element;\n statusBanner?: ReactNode;\n isLoadingInitial?: boolean;\n virtualize?: boolean;\n variant?: 'page' | 'embedded';\n showFilters?: boolean;\n filterDrawerState?: BackofficeFilterDrawerState;\n};\n\nexport const BackofficeEntityListScaffold = <RowView,>(\n props: Props<RowView>,\n): JSX.Element | null => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const {\n config,\n state,\n pushState,\n rows,\n getRowId,\n columns,\n gridTemplateColumns,\n hasNextPage,\n isLoadingMore,\n isRefreshing = false,\n onLoadMore,\n onRefresh,\n totalCount,\n loadedCountLabel,\n emptyState,\n statusBanner,\n header,\n headerActions,\n isLoadingInitial = false,\n variant = 'page',\n showFilters = true,\n } = props;\n const listConfig = config.list;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const listDefaults = config.listDefaults ??\n listConfig.defaultState ?? { where: null, sort: null };\n\n const columnsWithPrimary = useMemo(() => {\n const hasPrimary = columns.some((col) => {\n return col.isPrimary === true;\n });\n if (hasPrimary || columns.length === 0) {\n return columns;\n }\n return columns.map((col, index) => {\n const { header } = col;\n if (index === 0) {\n return { ...col, isPrimary: true, header };\n }\n return { ...col, header };\n });\n }, [columns]);\n\n const chips = useMemo<readonly FilterChip[]>(() => {\n const out: FilterChip[] = [];\n for (const filter of listConfig.filters) {\n const raw = getFilterValue(filter, state.where);\n const displayValue = getFilterDisplayValue(filter, raw, {\n enumLabel: (value) => {\n if (filter.kind !== 'enum') {\n return value;\n }\n const match = filter.options.find((option) => {\n return option.value === value;\n });\n if (match != null) {\n return resolveLabel(match.label, tApp);\n }\n return value;\n },\n booleanLabel: (value) => {\n if (filter.kind === 'boolean') {\n if (value && filter.trueLabel != null) {\n return resolveLabel(filter.trueLabel, tApp);\n }\n if (!value && filter.falseLabel != null) {\n return resolveLabel(filter.falseLabel, tApp);\n }\n }\n if (value) {\n return t('filters.boolean.yes');\n }\n return t('filters.boolean.no');\n },\n fallbackBooleanLabels: {\n yes: t('filters.boolean.yes'),\n no: t('filters.boolean.no'),\n },\n });\n\n if (displayValue != null) {\n let idValue = String(raw);\n if (Array.isArray(raw)) {\n idValue = raw.join(',');\n }\n const label = (\n <span>\n {resolveLabel(filter.label, tApp)}: {displayValue}\n </span>\n );\n out.push({\n id: `${filter.id}:${idValue}`,\n label,\n onRemove: () => {\n const key = filter.whereKey ?? filter.id;\n const nextWhere = setWhereValue(\n state.where,\n key,\n null,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n },\n });\n }\n }\n return out;\n }, [listConfig.filters, pushState, state, t, tApp]);\n\n const handleClearAll = useCallback(() => {\n pushState({\n ...listDefaults,\n });\n }, [listDefaults, pushState]);\n const [localIsFilterDrawerOpen, setLocalIsFilterDrawerOpen] = useState(false);\n const [localFilterSearch, setLocalFilterSearch] = useState('');\n const drawerState = props.filterDrawerState ?? {\n isOpen: localIsFilterDrawerOpen,\n search: localFilterSearch,\n setOpen: setLocalIsFilterDrawerOpen,\n setSearch: setLocalFilterSearch,\n reset: () => {\n setLocalIsFilterDrawerOpen(false);\n setLocalFilterSearch('');\n },\n };\n const isFilterDrawerOpen = drawerState.isOpen;\n const filterSearch = drawerState.search;\n const setIsFilterDrawerOpen = drawerState.setOpen;\n const setFilterSearch = drawerState.setSearch;\n const resetFilterDrawer = drawerState.reset;\n\n const [pickerDialog, setPickerDialog] = useState<{\n entity: string;\n whereKey: keyof RuntimeWhere;\n label: string;\n mode: 'single' | 'list';\n currentIds?: readonly string[];\n path?: readonly string[];\n scope?: BackofficePickerScope<Record<string, unknown>>;\n } | null>(null);\n\n const renderFilterControl = useCallback(\n (filter: BackofficeFilterSpec<RuntimeWhere>): JSX.Element => {\n const key = filter.whereKey ?? filter.id;\n const candidate = getFilterValue(filter, state.where);\n let value = '';\n if (typeof candidate === 'string') {\n value = candidate;\n }\n if (typeof candidate === 'number' && Number.isFinite(candidate)) {\n value = String(candidate);\n }\n\n const filterLabelText = resolveLabel(filter.label, tApp);\n\n if (filter.kind === 'text') {\n const placeholderLabelText =\n filter.placeholderLabel != null\n ? resolveLabel(filter.placeholderLabel, tApp)\n : filterLabelText;\n let placeholder = t('filters.placeholders.search', {\n label: placeholderLabelText,\n });\n if (filter.placeholderText != null) {\n placeholder = resolveLabel(filter.placeholderText, tApp);\n }\n return (\n <DeferredFilterSearchInput\n value={value}\n onApply={(next) => {\n const nextWhere = setWhereValue(\n state.where,\n key,\n next,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n placeholder={placeholder}\n ariaLabel={placeholder}\n className={styles.filterInput}\n />\n );\n }\n\n if (filter.kind === 'datetime') {\n const placeholderLabelText =\n filter.placeholderLabel != null\n ? resolveLabel(filter.placeholderLabel, tApp)\n : filterLabelText;\n let placeholder = t('filters.placeholders.search', {\n label: placeholderLabelText,\n });\n if (filter.placeholderText != null) {\n placeholder = resolveLabel(filter.placeholderText, tApp);\n }\n return (\n <DeferredFilterSearchInput\n value={toDatetimeInputValue(value)}\n onApply={(next) => {\n const normalized = fromDatetimeInputValue(next);\n const nextWhere = setWhereValue(\n state.where,\n key,\n normalized,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n placeholder={placeholder}\n ariaLabel={placeholder}\n className={styles.filterInput}\n type=\"datetime-local\"\n />\n );\n }\n\n if (filter.kind === 'number') {\n const placeholderLabelText =\n filter.placeholderLabel != null\n ? resolveLabel(filter.placeholderLabel, tApp)\n : filterLabelText;\n let placeholder = t('filters.placeholders.search', {\n label: placeholderLabelText,\n });\n if (filter.placeholderText != null) {\n placeholder = resolveLabel(filter.placeholderText, tApp);\n }\n return (\n <DeferredFilterSearchInput\n value={value}\n onApply={(next) => {\n const normalized = next.trim();\n const parsed = normalized === '' ? null : Number(normalized);\n const nextWhere = setWhereValue(\n state.where,\n key,\n Number.isFinite(parsed) ? parsed : null,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n placeholder={placeholder}\n ariaLabel={placeholder}\n className={styles.filterInput}\n inputMode={filter.inputMode ?? 'numeric'}\n type=\"text\"\n />\n );\n }\n\n if (filter.kind === 'enum') {\n const options = [\n {\n id: 'any',\n value: '',\n label: t('filters.all', {\n label: filterLabelText,\n }),\n },\n ...filter.options.map((option) => {\n return {\n id: option.value,\n value: option.value,\n label: resolveLabel(option.label, tApp),\n };\n }),\n ];\n\n return (\n <SimpleSelect\n options={options}\n value={value}\n size=\"small\"\n ariaLabel={filterLabelText}\n onChange={(next) => {\n const nextWhere = setWhereValue(\n state.where,\n key,\n next,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n />\n );\n }\n\n if (filter.kind === 'boolean') {\n let current: boolean | null = null;\n if (typeof candidate === 'boolean') {\n current = candidate;\n }\n\n let selectValue = '';\n if (current === true) {\n selectValue = 'true';\n }\n if (current === false) {\n selectValue = 'false';\n }\n\n const trueLabel =\n filter.trueLabel != null\n ? resolveLabel(filter.trueLabel, tApp)\n : t('filters.boolean.yes');\n const falseLabel =\n filter.falseLabel != null\n ? resolveLabel(filter.falseLabel, tApp)\n : t('filters.boolean.no');\n const options = [\n {\n id: 'any',\n value: '',\n label: t('filters.all', {\n label: filterLabelText,\n }),\n },\n {\n id: 'true',\n value: 'true',\n label: trueLabel,\n },\n {\n id: 'false',\n value: 'false',\n label: falseLabel,\n },\n ];\n\n return (\n <SimpleSelect\n options={options}\n value={selectValue}\n size=\"small\"\n ariaLabel={filterLabelText}\n onChange={(next) => {\n let parsed: boolean | null = null;\n if (next === 'true') {\n parsed = true;\n }\n if (next === 'false') {\n parsed = false;\n }\n const nextWhere = setWhereValue(\n state.where,\n key,\n parsed,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n />\n );\n }\n\n const pickerScope = (() => {\n if (filter.pickerScope == null) {\n return undefined;\n }\n if (typeof filter.pickerScope === 'function') {\n return filter.pickerScope(state.where);\n }\n return filter.pickerScope;\n })();\n\n if (filter.kind === 'entityIdList') {\n const currentIds = normalizeStringArray(candidate);\n const selectedCount = currentIds.length;\n const displayValue =\n selectedCount === 0\n ? null\n : t('filters.selectedEntities', {\n count: selectedCount,\n });\n\n const removeId = (id: string): void => {\n const nextIds = currentIds.filter((currentId) => {\n return currentId !== id;\n });\n const nextWhere = setWhereValue(\n state.where,\n key,\n nextIds.length === 0 ? null : nextIds,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n };\n\n return (\n <div className={styles.entityIdListFilter}>\n <EntityIdFilterField\n label={filterLabelText}\n value={selectedCount === 0 ? null : currentIds.join(',')}\n displayValue={displayValue}\n placeholder={t('filters.placeholders.anyEntity', {\n label: filterLabelText,\n })}\n onPick={() => {\n setPickerDialog({\n entity: filter.entity,\n whereKey: key,\n label: filterLabelText,\n mode: 'list',\n currentIds,\n path: filter.path,\n scope: pickerScope,\n });\n }}\n onClear={() => {\n const nextWhere = setWhereValue(\n state.where,\n key,\n null,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n />\n {currentIds.length > 0 ? (\n <div className={styles.entityIdListTags}>\n {currentIds.map((id) => {\n return (\n <Tag\n key={id}\n removeLabel={t('filters.actions.removeFilterValue', {\n label: filterLabelText,\n })}\n onRemove={() => {\n removeId(id);\n }}\n >\n <EntityFilterValue entityId={filter.entity} id={id} />\n </Tag>\n );\n })}\n </div>\n ) : null}\n </div>\n );\n }\n\n if (filter.kind === 'stringList') {\n const placeholderLabelText =\n filter.placeholderLabel != null\n ? resolveLabel(filter.placeholderLabel, tApp)\n : filterLabelText;\n let placeholder = t('filters.placeholders.search', {\n label: placeholderLabelText,\n });\n if (filter.placeholderText != null) {\n placeholder = resolveLabel(filter.placeholderText, tApp);\n }\n return (\n <DeferredFilterSearchInput\n value={value}\n onApply={(next) => {\n const values = next\n .split(/[\\n,]+/u)\n .map((entry) => {\n return entry.trim();\n })\n .filter((entry) => {\n return entry !== '';\n });\n const nextWhere = setWhereValue(\n state.where,\n key,\n values,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n placeholder={placeholder}\n ariaLabel={placeholder}\n className={styles.filterInput}\n />\n );\n }\n\n let currentId: string | null = null;\n if (typeof candidate === 'string') {\n currentId = candidate;\n }\n\n const renderField = (\n displayValue: string | null = null,\n isResolving = false,\n ) => {\n const normalizedDisplayValue = displayValue?.trim() ?? '';\n return (\n <EntityIdFilterField\n label={filterLabelText}\n value={currentId}\n displayValue={normalizedDisplayValue}\n isResolving={isResolving}\n placeholder={t('filters.placeholders.anyEntity', {\n label: filterLabelText,\n })}\n onPick={() => {\n setPickerDialog({\n entity: filter.entity,\n whereKey: key,\n label: filterLabelText,\n mode: 'single',\n path: filter.path,\n scope: pickerScope,\n });\n }}\n onClear={() => {\n const nextWhere = setWhereValue(\n state.where,\n key,\n null,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n />\n );\n };\n\n if (currentId == null || currentId.trim() === '') {\n return renderField();\n }\n\n return (\n <EntityFilterValueText entityId={filter.entity} id={currentId}>\n {(label, valueState) => {\n const isResolving = valueState?.status === 'loading';\n return renderField(\n isResolving ? t('common.loading') : label,\n isResolving,\n );\n }}\n </EntityFilterValueText>\n );\n },\n [pushState, state, t, tApp],\n );\n\n const hasPlacementConfig = useMemo(() => {\n return listConfig.filters.some((filter) => {\n return filter.placement != null;\n });\n }, [listConfig.filters]);\n\n const quickFilters = useMemo(() => {\n if (listConfig.filters.length === 0) {\n return [];\n }\n const maxPromotedFilters = listConfig.ui?.toolbar?.maxPromotedFilters ?? 3;\n if (hasPlacementConfig) {\n return listConfig.filters.filter((filter) => {\n return filter.placement === 'quick' || filter.placement === 'both';\n });\n }\n return listConfig.filters.slice(0, maxPromotedFilters);\n }, [listConfig.filters, listConfig.ui?.toolbar, hasPlacementConfig]);\n\n const drawerFilters = useMemo(() => {\n return listConfig.filters.filter((filter) => {\n if (filter.placement == null) {\n return true;\n }\n return filter.placement === 'drawer' || filter.placement === 'both';\n });\n }, [listConfig.filters]);\n\n const searchFilter = useMemo(() => {\n return quickFilters.find((filter) => {\n return filter.kind === 'text';\n });\n }, [quickFilters]);\n\n const quickFiltersNode = useMemo(() => {\n const visibleQuickFilters = quickFilters.filter((filter) => {\n return filter !== searchFilter;\n });\n\n if (visibleQuickFilters.length === 0) {\n return null;\n }\n\n return (\n <div className={styles.controlsRow}>\n {visibleQuickFilters.map((filter) => {\n return <span key={filter.id}>{renderFilterControl(filter)}</span>;\n })}\n </div>\n );\n }, [quickFilters, renderFilterControl, searchFilter]);\n\n const searchNode = useMemo(() => {\n if (searchFilter == null) {\n return null;\n }\n return renderFilterControl(searchFilter);\n }, [renderFilterControl, searchFilter]);\n\n const sortNode = useMemo(() => {\n if (listConfig.sorts.length === 0) {\n return null;\n }\n const firstSort = listConfig.sorts[0];\n if (firstSort == null) {\n return null;\n }\n const options = listConfig.sorts.map((s) => {\n return { id: s.id, value: s.id, label: resolveLabel(s.label, tApp) };\n });\n return (\n <SimpleSelect\n options={options}\n value={state.sort ?? firstSort.id}\n size=\"small\"\n ariaLabel={t('list.sort.label')}\n onChange={(next) => {\n pushState({\n ...state,\n sort: next,\n });\n }}\n />\n );\n }, [listConfig.sorts, pushState, state, t, tApp]);\n\n const chipsNode = useMemo(() => {\n if (chips.length === 0) {\n return null;\n }\n return <FilterChipRow chips={chips} onClearAll={handleClearAll} />;\n }, [chips, handleClearAll]);\n\n const drawerSections = useMemo(() => {\n if (drawerFilters.length === 0) {\n return [];\n }\n\n const normalizedQuery = filterSearch.trim().toLowerCase();\n const items: { id: string; node: JSX.Element }[] = [];\n\n for (const filter of drawerFilters) {\n const resolvedLabel = resolveLabel(filter.label, tApp);\n const matchesQuery =\n normalizedQuery === '' ||\n resolvedLabel.toLowerCase().includes(normalizedQuery);\n\n if (matchesQuery) {\n items.push({\n id: filter.id,\n node: (\n <BackofficeFilterField label={resolvedLabel}>\n {renderFilterControl(filter)}\n </BackofficeFilterField>\n ),\n });\n }\n }\n\n if (items.length === 0) {\n return [];\n }\n\n return [\n {\n id: 'backoffice.filters.sections.default',\n title: t('filters.sections.default'),\n items,\n },\n ];\n }, [drawerFilters, filterSearch, renderFilterControl, t, tApp]);\n\n const allFiltersNode = useMemo(() => {\n if (drawerFilters.length === 0) {\n return null;\n }\n const activeCount = chips.length;\n let label = t('filters.trigger');\n if (activeCount > 0) {\n label = t('filters.triggerWithCount', {\n count: activeCount,\n });\n }\n return (\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={() => {\n setIsFilterDrawerOpen(true);\n }}\n >\n {label}\n </Button>\n );\n }, [chips.length, drawerFilters.length, setIsFilterDrawerOpen, t]);\n\n const filterDrawerEmptyLabel =\n filterSearch.trim() === ''\n ? undefined\n : t('filters.drawer.emptySearchResults');\n\n const filterDrawerNode = (\n <BackofficeFilterDrawer\n isOpen={isFilterDrawerOpen}\n onClose={() => {\n resetFilterDrawer();\n }}\n sections={drawerSections}\n searchValue={filterSearch}\n onSearchChange={(next) => {\n setFilterSearch(next);\n }}\n onReset={handleClearAll}\n emptyLabel={filterDrawerEmptyLabel}\n />\n );\n\n const resolvedEmptyState = useMemo((): JSX.Element => {\n if (emptyState != null) {\n return emptyState;\n }\n\n if (isLoadingInitial) {\n return (\n <BackofficeTableSkeleton\n variant=\"embedded\"\n ariaLabel={t('common.loading')}\n />\n );\n }\n\n if (chips.length > 0) {\n return (\n <BackofficeEmptyState\n title={t('emptyState.listEmpty.title')}\n description={t('emptyState.listEmptyFiltered.description')}\n actions={\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={handleClearAll}\n >\n {t('emptyState.listEmptyFiltered.actions.reset')}\n </Button>\n }\n />\n );\n }\n\n return (\n <BackofficeEmptyState\n title={t('emptyState.listEmpty.title')}\n description={t('emptyState.listEmpty.description')}\n />\n );\n }, [chips.length, emptyState, handleClearAll, isLoadingInitial, t]);\n\n const tableFooterMeta = useMemo((): ReactNode => {\n if (loadedCountLabel != null) {\n return loadedCountLabel;\n }\n if (typeof totalCount !== 'number') {\n if (rows.length === 0) {\n return null;\n }\n return (\n <span>\n {t('list.loaded', {\n count: rows.length,\n })}\n </span>\n );\n }\n return (\n <span>\n {t('list.showing', {\n shown: rows.length,\n total: totalCount,\n })}\n </span>\n );\n }, [loadedCountLabel, rows.length, t, totalCount]);\n\n const runtimeConfig = useMemo(() => {\n const resolvedDisplayMode =\n listConfig.ui?.displayMode ?? listConfig.responsive?.mode ?? 'auto';\n return resolveBackofficeListRuntimeConfig({\n kind: listConfig.kind,\n displayMode: resolvedDisplayMode,\n ui: listConfig.ui,\n });\n }, [listConfig.kind, listConfig.responsive?.mode, listConfig.ui]);\n\n const hasKnownRemainingRows =\n typeof totalCount === 'number' && rows.length < totalCount;\n const hasInconsistentPageInfo = hasKnownRemainingRows && !hasNextPage;\n\n useEffect(() => {\n if (\n !hasInconsistentPageInfo ||\n !runtimeConfig.infiniteScroll.showInconsistentPageInfo ||\n !isDevEnv()\n ) {\n return;\n }\n // eslint-disable-next-line no-console\n console.warn(\n 'Backoffice list received inconsistent pageInfo: loaded rows are lower than totalCount but hasNextPage is false.',\n {\n entityId: config.id,\n loadedCount: rows.length,\n totalCount,\n },\n );\n }, [\n config.id,\n hasInconsistentPageInfo,\n rows.length,\n runtimeConfig.infiniteScroll.showInconsistentPageInfo,\n totalCount,\n ]);\n\n const shouldVirtualizeTable =\n props.virtualize === true || runtimeConfig.virtualization.enabled;\n\n const { sentinelRef } = useBackofficeInfiniteScrollSentinel({\n enabled: !shouldVirtualizeTable && runtimeConfig.infiniteScroll.enabled,\n hasNextPage,\n isLoading: isLoadingMore,\n onIntersect: onLoadMore,\n rootMargin: runtimeConfig.infiniteScroll.rootMargin,\n threshold: runtimeConfig.infiniteScroll.threshold,\n });\n\n const headerTitle = header?.title ?? resolveLabel(listConfig.title, tApp);\n const headerSubtitle = header?.subtitle;\n\n const actionColumn = columnsWithPrimary.find((column) => {\n return column.mobileRole === 'action' || column.id === 'actions';\n });\n const listMode =\n listConfig.ui?.displayMode ?? listConfig.responsive?.mode ?? 'auto';\n const listDensity =\n listConfig.ui?.density ?? listConfig.responsive?.density ?? 'compact';\n\n const tableInnerNode = shouldVirtualizeTable ? (\n <VirtualizedConnectionTable\n columns={columnsWithPrimary}\n rows={rows}\n getRowId={getRowId}\n emptyState={resolvedEmptyState}\n className={denseTableClass}\n gridTemplateColumns={gridTemplateColumns}\n virtualization={runtimeConfig.virtualization}\n infiniteScroll={{\n enabled: runtimeConfig.infiniteScroll.enabled,\n thresholdPx: runtimeConfig.infiniteScroll.thresholdPx,\n autoLoad: runtimeConfig.infiniteScroll.autoLoad,\n }}\n hasNextPage={hasNextPage}\n isLoadingMore={isLoadingMore}\n onLoadMore={onLoadMore}\n bodyScrollMode={BACKOFFICE_LIST_BODY_SCROLL_MODE}\n />\n ) : (\n <ResponsiveRecordList\n columns={columnsWithPrimary}\n rows={rows}\n getRowId={getRowId}\n emptyState={resolvedEmptyState}\n className={denseTableClass}\n gridTemplateColumns={gridTemplateColumns}\n mode={listMode}\n density={listDensity}\n bodyScrollMode={BACKOFFICE_LIST_BODY_SCROLL_MODE}\n bodyFooterNode={\n runtimeConfig.infiniteScroll.enabled ? (\n <div ref={sentinelRef} aria-hidden=\"true\" />\n ) : null\n }\n renderAction={(row) => {\n return actionColumn?.cell(row) ?? null;\n }}\n />\n );\n\n const tableNodeWithErrorBoundary = (\n <BackofficeErrorBoundary\n fallback={(args: { error: unknown; reset: () => void }) => {\n const { reset } = args;\n\n const retry = (): void => {\n reset();\n if (onRefresh != null) {\n onRefresh();\n }\n };\n\n return (\n <InlineBanner\n tone=\"danger\"\n title={t('list.errors.title')}\n actions={\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={retry}\n >\n {t('list.actions.retry')}\n </Button>\n }\n >\n {t('list.errors.tableFailed')}\n </InlineBanner>\n );\n }}\n >\n {tableInnerNode}\n </BackofficeErrorBoundary>\n );\n\n const filtersBarNode = showFilters ? (\n <>\n <BackofficeToolbar\n search={searchNode}\n primaryFilters={quickFiltersNode}\n filterDrawerTrigger={allFiltersNode}\n sort={sortNode}\n utilityActions={\n onRefresh == null ? null : (\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n isLoading={isRefreshing}\n loadingLabel={t('list.actions.refreshing')}\n onClick={() => {\n onRefresh();\n }}\n >\n {t('list.actions.refresh')}\n </Button>\n )\n }\n chips={chipsNode}\n density=\"compact\"\n />\n {filterDrawerNode}\n </>\n ) : null;\n\n const tableNode = (\n <div\n className={styles.tableHost}\n aria-busy={isRefreshing ? 'true' : undefined}\n >\n {isRefreshing && !isLoadingInitial ? (\n <div className={styles.refreshingIndicator} role=\"status\">\n <Spinner size={14} ariaLabel={t('list.refreshingRows')} />\n <span>{t('list.refreshingRows')}</span>\n </div>\n ) : null}\n {tableNodeWithErrorBoundary}\n <EntityIdPickerDialog\n isOpen={pickerDialog != null}\n entity={pickerDialog?.entity ?? config.id}\n title={pickerDialog?.label ?? t('picker.title')}\n scope={pickerDialog?.scope}\n onClose={() => {\n setPickerDialog(null);\n }}\n onSelectId={(id) => {\n if (pickerDialog == null) {\n return;\n }\n if (pickerDialog.mode === 'list') {\n const currentIds = pickerDialog.currentIds ?? [];\n const nextIds = currentIds.includes(id)\n ? currentIds\n : [...currentIds, id];\n const nextWhere = setWhereValue(\n state.where,\n pickerDialog.whereKey,\n nextIds,\n pickerDialog.path,\n );\n setIsFilterDrawerOpen(true);\n pushState({ ...state, where: nextWhere });\n return;\n }\n const nextWhere = setWhereValue(\n state.where,\n pickerDialog.whereKey,\n id,\n pickerDialog.path,\n );\n setIsFilterDrawerOpen(true);\n pushState({ ...state, where: nextWhere });\n }}\n />\n </div>\n );\n\n const shouldRenderTableFooter =\n rows.length > 0 || isLoadingMore || hasNextPage;\n\n const tableFooterNode = shouldRenderTableFooter ? (\n <>\n <BackofficeListFooter\n mode=\"status\"\n loadedCount={rows.length}\n totalCount={totalCount}\n hasNextPage={hasNextPage}\n isLoading={isLoadingMore}\n pageInfoState={\n hasInconsistentPageInfo\n ? 'inconsistent'\n : isLoadingMore\n ? 'loading'\n : hasNextPage\n ? 'ready'\n : 'complete'\n }\n labels={{\n loaded: tableFooterMeta,\n loading: t('list.loadMore.loading'),\n end: t('list.loadMore.end'),\n }}\n />\n </>\n ) : null;\n\n if (variant === 'embedded') {\n return (\n <BackofficeListFilterProvider\n config={config}\n state={state}\n pushState={pushState}\n >\n <div className={styles.embeddedContainer}>\n <div className={styles.embeddedHeader}>{headerTitle}</div>\n {filtersBarNode}\n {statusBanner}\n {tableNode}\n {tableFooterNode}\n </div>\n </BackofficeListFilterProvider>\n );\n }\n\n return (\n <BackofficeListFilterProvider\n config={config}\n state={state}\n pushState={pushState}\n >\n <ListPageTemplate\n headerNode={\n <BackofficePageHeader\n title={headerTitle}\n subtitle={headerSubtitle}\n actions={headerActions}\n />\n }\n toolbarNode={filtersBarNode}\n statusNode={statusBanner}\n tableNode={tableNode}\n tableFooterNode={tableFooterNode}\n presentation=\"flat\"\n bodyScrollMode={BACKOFFICE_LIST_BODY_SCROLL_MODE}\n />\n </BackofficeListFilterProvider>\n );\n};\n\nexport default BackofficeEntityListScaffold;\n"],"mappings":"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"}
1
+ {"version":3,"file":"BackofficeEntityListScaffold.js","names":[],"sources":["../../../../../src/components/backoffice/scaffolds/BackofficeEntityListScaffold.tsx"],"sourcesContent":["/* eslint-disable no-ternary */\nimport {\n type JSX,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport type { TFunction } from 'i18next';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@plumile/ui/atomic/atoms/button/Button.js';\nimport { BackofficeEmptyState } from '@plumile/ui/backoffice/molecules/backoffice_empty_state/BackofficeEmptyState.js';\nimport { BackofficeFilterDrawer } from '@plumile/ui/backoffice/molecules/backoffice_filter_drawer/BackofficeFilterDrawer.js';\nimport { BackofficeFilterField } from '@plumile/ui/backoffice/molecules/backoffice_filter_field/BackofficeFilterField.js';\nimport { Spinner } from '@plumile/ui/backoffice/atoms/spinner/Spinner.js';\nimport { Tag } from '@plumile/ui/backoffice/atoms/tag/Tag.js';\nimport { BackofficeListFooter } from '@plumile/ui/backoffice/molecules/backoffice_list_footer/BackofficeListFooter.js';\nimport { BackofficePageHeader } from '@plumile/ui/backoffice/molecules/backoffice_page_header/BackofficePageHeader.js';\nimport { BackofficeToolbar } from '@plumile/ui/backoffice/molecules/backoffice_toolbar/BackofficeToolbar.js';\nimport { BackofficeTableSkeleton } from '@plumile/ui/backoffice/molecules/backoffice_table_skeleton/BackofficeTableSkeleton.js';\nimport {\n FilterChipRow,\n type FilterChip,\n} from '@plumile/ui/backoffice/molecules/filter_chip_row/FilterChipRow.js';\nimport { InlineBanner } from '@plumile/ui/components/feedback/InlineBanner.js';\nimport { ListPageTemplate } from '@plumile/ui/backoffice/templates/list_page_template/ListPageTemplate.js';\nimport {\n type DataTableColumn,\n type GetRowId,\n} from '@plumile/ui/components/data-table/DataTable.js';\nimport { ResponsiveRecordList } from '@plumile/ui/components/data-table/ResponsiveRecordList.js';\nimport { VirtualizedConnectionTable } from '@plumile/ui/components/data-table/VirtualizedConnectionTable.js';\nimport { SimpleSelect } from '@plumile/ui/components/select/SimpleSelect.js';\nimport { denseTableClass } from '@plumile/ui/shared/backofficeTableDensity.css.js';\n\nimport {\n readWhereValue,\n setWhereValue,\n} from '@plumile/backoffice-core/filters/where.js';\nimport { resolveBackofficeListRuntimeConfig } from '@plumile/backoffice-core/config/listRuntime.js';\nimport type {\n BackofficeFilterSpec,\n BackofficeListState,\n BackofficePickerScope,\n BackofficeRuntimeResolvedListFacetConfig,\n I18nLabel,\n} from '@plumile/backoffice-core/types.js';\n\nimport { BackofficeErrorBoundary } from '../errors/BackofficeErrorBoundary.js';\nimport {\n EntityFilterValue,\n EntityFilterValueText,\n} from '../filters/EntityFilterValue.js';\nimport { EntityIdPickerDialog } from '../pickers/EntityIdPickerDialog.js';\nimport { EntityIdFilterField } from '../filters/EntityIdFilterField.js';\nimport { DeferredFilterSearchInput } from '../filters/DeferredFilterSearchInput.js';\nimport { BackofficeListFilterProvider } from './BackofficeListFilterContext.js';\nimport { BACKOFFICE_LIST_BODY_SCROLL_MODE } from './backofficeListScrollMode.js';\nimport { useBackofficeReactTranslation } from '../../../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeInfiniteScrollSentinel } from '../../../hooks/useBackofficeInfiniteScrollSentinel.js';\nimport type { BackofficeFilterDrawerState } from '../../../provider/BackofficeListUiStateContext.js';\nimport { isDevEnv } from '../../../relay/envHelpers.js';\n\nimport * as styles from './backofficeEntityListScaffold.css.js';\n\nconst resolveLabel = (label: I18nLabel, tApp: TFunction): string => {\n return label(tApp);\n};\n\nconst getFilterValue = <Where extends Record<string, unknown>>(\n filter: BackofficeFilterSpec<Where>,\n where: Where | null,\n): unknown => {\n if (filter.fromGraphQL != null && where != null) {\n return filter.fromGraphQL(where);\n }\n\n const key = (filter.whereKey ?? filter.id) as keyof Where;\n return readWhereValue(where, key, filter.path);\n};\n\nconst normalizeStringArray = (value: unknown): readonly string[] => {\n if (!Array.isArray(value)) {\n return [];\n }\n return value\n .map((entry) => {\n if (entry == null) {\n return null;\n }\n const normalized = String(entry).trim();\n if (normalized === '') {\n return null;\n }\n return normalized;\n })\n .filter((entry): entry is string => {\n return entry != null;\n });\n};\n\nconst getFilterDisplayValue = <Where extends Record<string, unknown>>(\n filter: BackofficeFilterSpec<Where>,\n raw: unknown,\n options: {\n enumLabel: (value: string) => string;\n booleanLabel: (value: boolean) => string;\n fallbackBooleanLabels: { yes: string; no: string };\n },\n): ReactNode | null => {\n if (raw == null) {\n return null;\n }\n\n if (Array.isArray(raw)) {\n const normalized = normalizeStringArray(raw);\n\n if (normalized.length === 0) {\n return null;\n }\n\n if (filter.kind === 'entityIdList') {\n return (\n <>\n {normalized.map((id, index) => {\n return (\n <span key={id}>\n <EntityFilterValue entityId={filter.entity} id={id} />\n {index < normalized.length - 1 ? ', ' : null}\n </span>\n );\n })}\n </>\n );\n }\n\n return normalized.join(', ');\n }\n\n if (typeof raw === 'boolean') {\n if (filter.kind === 'boolean') {\n return options.booleanLabel(raw);\n }\n if (raw) {\n return options.fallbackBooleanLabels.yes;\n }\n return options.fallbackBooleanLabels.no;\n }\n\n if (typeof raw !== 'string' && typeof raw !== 'number') {\n return null;\n }\n\n const rawString = String(raw).trim();\n if (rawString === '') {\n return null;\n }\n\n if (filter.kind === 'entityId') {\n return <EntityFilterValue entityId={filter.entity} id={rawString} />;\n }\n\n if (filter.kind === 'enum') {\n return options.enumLabel(rawString);\n }\n\n return rawString;\n};\n\nconst toDatetimeInputValue = (value: string): string => {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) {\n return value;\n }\n const offsetMs = date.getTimezoneOffset() * 60_000;\n return new Date(date.getTime() - offsetMs).toISOString().slice(0, 16);\n};\n\nconst fromDatetimeInputValue = (value: string): string => {\n const normalized = value.trim();\n if (normalized === '') {\n return '';\n }\n const date = new Date(normalized);\n if (Number.isNaN(date.getTime())) {\n return normalized;\n }\n return date.toISOString();\n};\n\ntype RuntimeWhere = Record<string, unknown>;\ntype RuntimeSort = string;\n\ntype Props<RowView> = {\n config: BackofficeRuntimeResolvedListFacetConfig;\n state: BackofficeListState<RuntimeWhere, RuntimeSort>;\n pushState: (next: BackofficeListState<RuntimeWhere, RuntimeSort>) => void;\n header?: {\n title?: string;\n subtitle?: string;\n };\n headerActions?: ReactNode;\n rows: readonly RowView[];\n getRowId: GetRowId<RowView>;\n columns: readonly DataTableColumn<RowView>[];\n gridTemplateColumns?: string;\n hasNextPage: boolean;\n isLoadingMore: boolean;\n isRefreshing?: boolean;\n onLoadMore: () => void;\n onRefresh?: () => void;\n totalCount?: number | null;\n loadedCountLabel?: ReactNode;\n emptyState?: JSX.Element;\n statusBanner?: ReactNode;\n isLoadingInitial?: boolean;\n virtualize?: boolean;\n variant?: 'page' | 'embedded';\n showFilters?: boolean;\n filterDrawerState?: BackofficeFilterDrawerState;\n};\n\nexport const BackofficeEntityListScaffold = <RowView,>(\n props: Props<RowView>,\n): JSX.Element | null => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const {\n config,\n state,\n pushState,\n rows,\n getRowId,\n columns,\n gridTemplateColumns,\n hasNextPage,\n isLoadingMore,\n isRefreshing = false,\n onLoadMore,\n onRefresh,\n totalCount,\n loadedCountLabel,\n emptyState,\n statusBanner,\n header,\n headerActions,\n isLoadingInitial = false,\n variant = 'page',\n showFilters = true,\n } = props;\n const listConfig = config.list;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const listDefaults = config.listDefaults ??\n listConfig.defaultState ?? { where: null, sort: null };\n\n const columnsWithPrimary = useMemo(() => {\n const hasPrimary = columns.some((col) => {\n return col.isPrimary === true;\n });\n if (hasPrimary || columns.length === 0) {\n return columns;\n }\n return columns.map((col, index) => {\n const { header } = col;\n if (index === 0) {\n return { ...col, isPrimary: true, header };\n }\n return { ...col, header };\n });\n }, [columns]);\n\n const chips = useMemo<readonly FilterChip[]>(() => {\n const out: FilterChip[] = [];\n for (const filter of listConfig.filters) {\n const raw = getFilterValue(filter, state.where);\n const displayValue = getFilterDisplayValue(filter, raw, {\n enumLabel: (value) => {\n if (filter.kind !== 'enum') {\n return value;\n }\n const match = filter.options.find((option) => {\n return option.value === value;\n });\n if (match != null) {\n return resolveLabel(match.label, tApp);\n }\n return value;\n },\n booleanLabel: (value) => {\n if (filter.kind === 'boolean') {\n if (value && filter.trueLabel != null) {\n return resolveLabel(filter.trueLabel, tApp);\n }\n if (!value && filter.falseLabel != null) {\n return resolveLabel(filter.falseLabel, tApp);\n }\n }\n if (value) {\n return t('filters.boolean.yes');\n }\n return t('filters.boolean.no');\n },\n fallbackBooleanLabels: {\n yes: t('filters.boolean.yes'),\n no: t('filters.boolean.no'),\n },\n });\n\n if (displayValue != null) {\n let idValue = String(raw);\n if (Array.isArray(raw)) {\n idValue = raw.join(',');\n }\n const label = (\n <span>\n {resolveLabel(filter.label, tApp)}: {displayValue}\n </span>\n );\n out.push({\n id: `${filter.id}:${idValue}`,\n label,\n onRemove: () => {\n const key = filter.whereKey ?? filter.id;\n const nextWhere = setWhereValue(\n state.where,\n key,\n null,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n },\n });\n }\n }\n return out;\n }, [listConfig.filters, pushState, state, t, tApp]);\n\n const handleClearAll = useCallback(() => {\n pushState({\n ...listDefaults,\n });\n }, [listDefaults, pushState]);\n const [localIsFilterDrawerOpen, setLocalIsFilterDrawerOpen] = useState(false);\n const [localFilterSearch, setLocalFilterSearch] = useState('');\n const drawerState = props.filterDrawerState ?? {\n isOpen: localIsFilterDrawerOpen,\n search: localFilterSearch,\n setOpen: setLocalIsFilterDrawerOpen,\n setSearch: setLocalFilterSearch,\n reset: () => {\n setLocalIsFilterDrawerOpen(false);\n setLocalFilterSearch('');\n },\n };\n const isFilterDrawerOpen = drawerState.isOpen;\n const filterSearch = drawerState.search;\n const setIsFilterDrawerOpen = drawerState.setOpen;\n const setFilterSearch = drawerState.setSearch;\n const resetFilterDrawer = drawerState.reset;\n\n const [pickerDialog, setPickerDialog] = useState<{\n entity: string;\n whereKey: keyof RuntimeWhere;\n label: string;\n mode: 'single' | 'list';\n currentIds?: readonly string[];\n path?: readonly string[];\n scope?: BackofficePickerScope<Record<string, unknown>>;\n } | null>(null);\n\n const renderFilterControl = useCallback(\n (filter: BackofficeFilterSpec<RuntimeWhere>): JSX.Element => {\n const key = filter.whereKey ?? filter.id;\n const candidate = getFilterValue(filter, state.where);\n let value = '';\n if (typeof candidate === 'string') {\n value = candidate;\n }\n if (typeof candidate === 'number' && Number.isFinite(candidate)) {\n value = String(candidate);\n }\n\n const filterLabelText = resolveLabel(filter.label, tApp);\n\n if (filter.kind === 'text') {\n const placeholderLabelText =\n filter.placeholderLabel != null\n ? resolveLabel(filter.placeholderLabel, tApp)\n : filterLabelText;\n let placeholder = t('filters.placeholders.search', {\n label: placeholderLabelText,\n });\n if (filter.placeholderText != null) {\n placeholder = resolveLabel(filter.placeholderText, tApp);\n }\n return (\n <DeferredFilterSearchInput\n value={value}\n onApply={(next) => {\n const nextWhere = setWhereValue(\n state.where,\n key,\n next,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n placeholder={placeholder}\n ariaLabel={placeholder}\n className={styles.filterInput}\n />\n );\n }\n\n if (filter.kind === 'datetime') {\n const placeholderLabelText =\n filter.placeholderLabel != null\n ? resolveLabel(filter.placeholderLabel, tApp)\n : filterLabelText;\n let placeholder = t('filters.placeholders.search', {\n label: placeholderLabelText,\n });\n if (filter.placeholderText != null) {\n placeholder = resolveLabel(filter.placeholderText, tApp);\n }\n return (\n <DeferredFilterSearchInput\n value={toDatetimeInputValue(value)}\n onApply={(next) => {\n const normalized = fromDatetimeInputValue(next);\n const nextWhere = setWhereValue(\n state.where,\n key,\n normalized,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n placeholder={placeholder}\n ariaLabel={placeholder}\n className={styles.filterInput}\n type=\"datetime-local\"\n />\n );\n }\n\n if (filter.kind === 'number') {\n const placeholderLabelText =\n filter.placeholderLabel != null\n ? resolveLabel(filter.placeholderLabel, tApp)\n : filterLabelText;\n let placeholder = t('filters.placeholders.search', {\n label: placeholderLabelText,\n });\n if (filter.placeholderText != null) {\n placeholder = resolveLabel(filter.placeholderText, tApp);\n }\n return (\n <DeferredFilterSearchInput\n value={value}\n onApply={(next) => {\n const normalized = next.trim();\n const parsed = normalized === '' ? null : Number(normalized);\n const nextWhere = setWhereValue(\n state.where,\n key,\n Number.isFinite(parsed) ? parsed : null,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n placeholder={placeholder}\n ariaLabel={placeholder}\n className={styles.filterInput}\n inputMode={filter.inputMode ?? 'numeric'}\n type=\"text\"\n />\n );\n }\n\n if (filter.kind === 'enum') {\n const options = [\n {\n id: 'any',\n value: '',\n label: t('filters.all', {\n label: filterLabelText,\n }),\n },\n ...filter.options.map((option) => {\n return {\n id: option.value,\n value: option.value,\n label: resolveLabel(option.label, tApp),\n };\n }),\n ];\n\n return (\n <SimpleSelect\n options={options}\n value={value}\n size=\"small\"\n ariaLabel={filterLabelText}\n onChange={(next) => {\n const nextWhere = setWhereValue(\n state.where,\n key,\n next,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n />\n );\n }\n\n if (filter.kind === 'boolean') {\n let current: boolean | null = null;\n if (typeof candidate === 'boolean') {\n current = candidate;\n }\n\n let selectValue = '';\n if (current === true) {\n selectValue = 'true';\n }\n if (current === false) {\n selectValue = 'false';\n }\n\n const trueLabel =\n filter.trueLabel != null\n ? resolveLabel(filter.trueLabel, tApp)\n : t('filters.boolean.yes');\n const falseLabel =\n filter.falseLabel != null\n ? resolveLabel(filter.falseLabel, tApp)\n : t('filters.boolean.no');\n const options = [\n {\n id: 'any',\n value: '',\n label: t('filters.all', {\n label: filterLabelText,\n }),\n },\n {\n id: 'true',\n value: 'true',\n label: trueLabel,\n },\n {\n id: 'false',\n value: 'false',\n label: falseLabel,\n },\n ];\n\n return (\n <SimpleSelect\n options={options}\n value={selectValue}\n size=\"small\"\n ariaLabel={filterLabelText}\n onChange={(next) => {\n let parsed: boolean | null = null;\n if (next === 'true') {\n parsed = true;\n }\n if (next === 'false') {\n parsed = false;\n }\n const nextWhere = setWhereValue(\n state.where,\n key,\n parsed,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n />\n );\n }\n\n const pickerScope = (() => {\n if (filter.pickerScope == null) {\n return undefined;\n }\n if (typeof filter.pickerScope === 'function') {\n return filter.pickerScope(state.where);\n }\n return filter.pickerScope;\n })();\n\n if (filter.kind === 'entityIdList') {\n const currentIds = normalizeStringArray(candidate);\n const selectedCount = currentIds.length;\n const displayValue =\n selectedCount === 0\n ? null\n : t('filters.selectedEntities', {\n count: selectedCount,\n });\n\n const removeId = (id: string): void => {\n const nextIds = currentIds.filter((currentId) => {\n return currentId !== id;\n });\n const nextWhere = setWhereValue(\n state.where,\n key,\n nextIds.length === 0 ? null : nextIds,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n };\n\n return (\n <div className={styles.entityIdListFilter}>\n <EntityIdFilterField\n label={filterLabelText}\n value={selectedCount === 0 ? null : currentIds.join(',')}\n displayValue={displayValue}\n placeholder={t('filters.placeholders.anyEntity', {\n label: filterLabelText,\n })}\n onPick={() => {\n setPickerDialog({\n entity: filter.entity,\n whereKey: key,\n label: filterLabelText,\n mode: 'list',\n currentIds,\n path: filter.path,\n scope: pickerScope,\n });\n }}\n onClear={() => {\n const nextWhere = setWhereValue(\n state.where,\n key,\n null,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n />\n {currentIds.length > 0 ? (\n <div className={styles.entityIdListTags}>\n {currentIds.map((id) => {\n return (\n <Tag\n key={id}\n removeLabel={t('filters.actions.removeFilterValue', {\n label: filterLabelText,\n })}\n onRemove={() => {\n removeId(id);\n }}\n >\n <EntityFilterValue entityId={filter.entity} id={id} />\n </Tag>\n );\n })}\n </div>\n ) : null}\n </div>\n );\n }\n\n if (filter.kind === 'stringList') {\n const placeholderLabelText =\n filter.placeholderLabel != null\n ? resolveLabel(filter.placeholderLabel, tApp)\n : filterLabelText;\n let placeholder = t('filters.placeholders.search', {\n label: placeholderLabelText,\n });\n if (filter.placeholderText != null) {\n placeholder = resolveLabel(filter.placeholderText, tApp);\n }\n return (\n <DeferredFilterSearchInput\n value={value}\n onApply={(next) => {\n const values = next\n .split(/[\\n,]+/u)\n .map((entry) => {\n return entry.trim();\n })\n .filter((entry) => {\n return entry !== '';\n });\n const nextWhere = setWhereValue(\n state.where,\n key,\n values,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n placeholder={placeholder}\n ariaLabel={placeholder}\n className={styles.filterInput}\n />\n );\n }\n\n let currentId: string | null = null;\n if (typeof candidate === 'string') {\n currentId = candidate;\n }\n\n const renderField = (\n displayValue: string | null = null,\n isResolving = false,\n ) => {\n const normalizedDisplayValue = displayValue?.trim() ?? '';\n return (\n <EntityIdFilterField\n label={filterLabelText}\n value={currentId}\n displayValue={normalizedDisplayValue}\n isResolving={isResolving}\n placeholder={t('filters.placeholders.anyEntity', {\n label: filterLabelText,\n })}\n onPick={() => {\n setPickerDialog({\n entity: filter.entity,\n whereKey: key,\n label: filterLabelText,\n mode: 'single',\n path: filter.path,\n scope: pickerScope,\n });\n }}\n onClear={() => {\n const nextWhere = setWhereValue(\n state.where,\n key,\n null,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n />\n );\n };\n\n if (currentId == null || currentId.trim() === '') {\n return renderField();\n }\n\n return (\n <EntityFilterValueText entityId={filter.entity} id={currentId}>\n {(label, valueState) => {\n const isResolving = valueState?.status === 'loading';\n return renderField(\n isResolving ? t('common.loading') : label,\n isResolving,\n );\n }}\n </EntityFilterValueText>\n );\n },\n [pushState, state, t, tApp],\n );\n\n const hasPlacementConfig = useMemo(() => {\n return listConfig.filters.some((filter) => {\n return filter.placement != null;\n });\n }, [listConfig.filters]);\n\n const quickFilters = useMemo(() => {\n if (listConfig.filters.length === 0) {\n return [];\n }\n const maxPromotedFilters = listConfig.ui?.toolbar?.maxPromotedFilters ?? 3;\n if (hasPlacementConfig) {\n return listConfig.filters.filter((filter) => {\n return filter.placement === 'quick' || filter.placement === 'both';\n });\n }\n return listConfig.filters.slice(0, maxPromotedFilters);\n }, [listConfig.filters, listConfig.ui?.toolbar, hasPlacementConfig]);\n\n const drawerFilters = useMemo(() => {\n return listConfig.filters.filter((filter) => {\n if (filter.placement == null) {\n return true;\n }\n return filter.placement === 'drawer' || filter.placement === 'both';\n });\n }, [listConfig.filters]);\n\n const searchFilter = useMemo(() => {\n return quickFilters.find((filter) => {\n return filter.kind === 'text';\n });\n }, [quickFilters]);\n\n const quickFiltersNode = useMemo(() => {\n const visibleQuickFilters = quickFilters.filter((filter) => {\n return filter !== searchFilter;\n });\n\n if (visibleQuickFilters.length === 0) {\n return null;\n }\n\n return (\n <div className={styles.controlsRow}>\n {visibleQuickFilters.map((filter) => {\n return <span key={filter.id}>{renderFilterControl(filter)}</span>;\n })}\n </div>\n );\n }, [quickFilters, renderFilterControl, searchFilter]);\n\n const searchNode = useMemo(() => {\n if (searchFilter == null) {\n return null;\n }\n return renderFilterControl(searchFilter);\n }, [renderFilterControl, searchFilter]);\n\n const sortNode = useMemo(() => {\n if (listConfig.sorts.length === 0) {\n return null;\n }\n const firstSort = listConfig.sorts[0];\n if (firstSort == null) {\n return null;\n }\n const options = listConfig.sorts.map((s) => {\n return { id: s.id, value: s.id, label: resolveLabel(s.label, tApp) };\n });\n return (\n <SimpleSelect\n options={options}\n value={state.sort ?? firstSort.id}\n size=\"small\"\n ariaLabel={t('list.sort.label')}\n onChange={(next) => {\n pushState({\n ...state,\n sort: next,\n });\n }}\n />\n );\n }, [listConfig.sorts, pushState, state, t, tApp]);\n\n const chipsNode = useMemo(() => {\n if (chips.length === 0) {\n return null;\n }\n return <FilterChipRow chips={chips} onClearAll={handleClearAll} />;\n }, [chips, handleClearAll]);\n\n const drawerSections = useMemo(() => {\n if (drawerFilters.length === 0) {\n return [];\n }\n\n const normalizedQuery = filterSearch.trim().toLowerCase();\n const items: { id: string; node: JSX.Element }[] = [];\n\n for (const filter of drawerFilters) {\n const resolvedLabel = resolveLabel(filter.label, tApp);\n const matchesQuery =\n normalizedQuery === '' ||\n resolvedLabel.toLowerCase().includes(normalizedQuery);\n\n if (matchesQuery) {\n items.push({\n id: filter.id,\n node: (\n <BackofficeFilterField label={resolvedLabel}>\n {renderFilterControl(filter)}\n </BackofficeFilterField>\n ),\n });\n }\n }\n\n if (items.length === 0) {\n return [];\n }\n\n return [\n {\n id: 'backoffice.filters.sections.default',\n title: t('filters.sections.default'),\n items,\n },\n ];\n }, [drawerFilters, filterSearch, renderFilterControl, t, tApp]);\n\n const allFiltersNode = useMemo(() => {\n if (drawerFilters.length === 0) {\n return null;\n }\n const activeCount = chips.length;\n let label = t('filters.trigger');\n if (activeCount > 0) {\n label = t('filters.triggerWithCount', {\n count: activeCount,\n });\n }\n return (\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={() => {\n setIsFilterDrawerOpen(true);\n }}\n >\n {label}\n </Button>\n );\n }, [chips.length, drawerFilters.length, setIsFilterDrawerOpen, t]);\n\n const filterDrawerEmptyLabel =\n filterSearch.trim() === ''\n ? undefined\n : t('filters.drawer.emptySearchResults');\n\n const filterDrawerNode = (\n <BackofficeFilterDrawer\n isOpen={isFilterDrawerOpen}\n onClose={() => {\n resetFilterDrawer();\n }}\n sections={drawerSections}\n searchValue={filterSearch}\n onSearchChange={(next) => {\n setFilterSearch(next);\n }}\n onReset={handleClearAll}\n emptyLabel={filterDrawerEmptyLabel}\n />\n );\n\n const resolvedEmptyState = useMemo((): JSX.Element => {\n if (emptyState != null) {\n return emptyState;\n }\n\n if (isLoadingInitial) {\n return (\n <BackofficeTableSkeleton\n variant=\"embedded\"\n ariaLabel={t('common.loading')}\n />\n );\n }\n\n if (chips.length > 0) {\n return (\n <BackofficeEmptyState\n title={t('emptyState.listEmpty.title')}\n description={t('emptyState.listEmptyFiltered.description')}\n actions={\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={handleClearAll}\n >\n {t('emptyState.listEmptyFiltered.actions.reset')}\n </Button>\n }\n />\n );\n }\n\n return (\n <BackofficeEmptyState\n title={t('emptyState.listEmpty.title')}\n description={t('emptyState.listEmpty.description')}\n />\n );\n }, [chips.length, emptyState, handleClearAll, isLoadingInitial, t]);\n\n const tableFooterMeta = useMemo((): ReactNode => {\n if (loadedCountLabel != null) {\n return loadedCountLabel;\n }\n if (typeof totalCount !== 'number') {\n if (rows.length === 0) {\n return null;\n }\n return (\n <span>\n {t('list.loaded', {\n count: rows.length,\n })}\n </span>\n );\n }\n return (\n <span>\n {t('list.showing', {\n shown: rows.length,\n total: totalCount,\n })}\n </span>\n );\n }, [loadedCountLabel, rows.length, t, totalCount]);\n\n const runtimeConfig = useMemo(() => {\n const resolvedDisplayMode =\n listConfig.ui?.displayMode ?? listConfig.responsive?.mode ?? 'auto';\n return resolveBackofficeListRuntimeConfig({\n kind: listConfig.kind,\n displayMode: resolvedDisplayMode,\n ui: listConfig.ui,\n });\n }, [listConfig.kind, listConfig.responsive?.mode, listConfig.ui]);\n\n const hasKnownRemainingRows =\n typeof totalCount === 'number' && rows.length < totalCount;\n const hasInconsistentPageInfo = hasKnownRemainingRows && !hasNextPage;\n\n useEffect(() => {\n if (\n !hasInconsistentPageInfo ||\n !runtimeConfig.infiniteScroll.showInconsistentPageInfo ||\n !isDevEnv()\n ) {\n return;\n }\n // eslint-disable-next-line no-console\n console.warn(\n 'Backoffice list received inconsistent pageInfo: loaded rows are lower than totalCount but hasNextPage is false.',\n {\n entityId: config.id,\n loadedCount: rows.length,\n totalCount,\n },\n );\n }, [\n config.id,\n hasInconsistentPageInfo,\n rows.length,\n runtimeConfig.infiniteScroll.showInconsistentPageInfo,\n totalCount,\n ]);\n\n const shouldVirtualizeTable =\n props.virtualize === true || runtimeConfig.virtualization.enabled;\n\n const { sentinelRef } = useBackofficeInfiniteScrollSentinel({\n enabled: !shouldVirtualizeTable && runtimeConfig.infiniteScroll.enabled,\n hasNextPage,\n isLoading: isLoadingMore,\n onIntersect: onLoadMore,\n rootMargin: runtimeConfig.infiniteScroll.rootMargin,\n threshold: runtimeConfig.infiniteScroll.threshold,\n });\n\n const headerTitle = header?.title ?? resolveLabel(listConfig.title, tApp);\n const headerSubtitle = header?.subtitle;\n\n const actionColumn = columnsWithPrimary.find((column) => {\n return column.mobileRole === 'action' || column.id === 'actions';\n });\n const listMode =\n listConfig.ui?.displayMode ?? listConfig.responsive?.mode ?? 'auto';\n const listDensity =\n listConfig.ui?.density ?? listConfig.responsive?.density ?? 'compact';\n\n const tableInnerNode = shouldVirtualizeTable ? (\n <VirtualizedConnectionTable\n columns={columnsWithPrimary}\n rows={rows}\n getRowId={getRowId}\n emptyState={resolvedEmptyState}\n className={denseTableClass}\n gridTemplateColumns={gridTemplateColumns}\n virtualization={runtimeConfig.virtualization}\n infiniteScroll={{\n enabled: runtimeConfig.infiniteScroll.enabled,\n thresholdPx: runtimeConfig.infiniteScroll.thresholdPx,\n autoLoad: runtimeConfig.infiniteScroll.autoLoad,\n }}\n hasNextPage={hasNextPage}\n isLoadingMore={isLoadingMore}\n onLoadMore={onLoadMore}\n bodyScrollMode={BACKOFFICE_LIST_BODY_SCROLL_MODE}\n />\n ) : (\n <ResponsiveRecordList\n columns={columnsWithPrimary}\n rows={rows}\n getRowId={getRowId}\n emptyState={resolvedEmptyState}\n className={denseTableClass}\n gridTemplateColumns={gridTemplateColumns}\n mode={listMode}\n density={listDensity}\n bodyScrollMode={BACKOFFICE_LIST_BODY_SCROLL_MODE}\n bodyFooterNode={\n runtimeConfig.infiniteScroll.enabled ? (\n <div ref={sentinelRef} aria-hidden=\"true\" />\n ) : null\n }\n renderAction={(row) => {\n return actionColumn?.cell(row) ?? null;\n }}\n />\n );\n\n const tableNodeWithErrorBoundary = (\n <BackofficeErrorBoundary\n fallback={(args: { error: unknown; reset: () => void }) => {\n const { reset } = args;\n\n const retry = (): void => {\n reset();\n if (onRefresh != null) {\n onRefresh();\n }\n };\n\n return (\n <InlineBanner\n tone=\"danger\"\n title={t('list.errors.title')}\n actions={\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={retry}\n >\n {t('list.actions.retry')}\n </Button>\n }\n >\n {t('list.errors.tableFailed')}\n </InlineBanner>\n );\n }}\n >\n {tableInnerNode}\n </BackofficeErrorBoundary>\n );\n\n const filtersBarNode = showFilters ? (\n <>\n <BackofficeToolbar\n search={searchNode}\n primaryFilters={quickFiltersNode}\n filterDrawerTrigger={allFiltersNode}\n sort={sortNode}\n utilityActions={\n onRefresh == null ? null : (\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n isLoading={isRefreshing}\n loadingLabel={t('list.actions.refreshing')}\n onClick={() => {\n onRefresh();\n }}\n >\n {t('list.actions.refresh')}\n </Button>\n )\n }\n chips={chipsNode}\n density=\"compact\"\n />\n {filterDrawerNode}\n </>\n ) : null;\n\n const tableNode = (\n <div\n className={styles.tableHost}\n aria-busy={isRefreshing ? 'true' : undefined}\n >\n {isRefreshing && !isLoadingInitial ? (\n <div className={styles.refreshingIndicator} role=\"status\">\n <Spinner size={14} ariaLabel={t('list.refreshingRows')} />\n <span>{t('list.refreshingRows')}</span>\n </div>\n ) : null}\n {tableNodeWithErrorBoundary}\n <EntityIdPickerDialog\n isOpen={pickerDialog != null}\n entity={pickerDialog?.entity ?? config.id}\n title={pickerDialog?.label ?? t('picker.title')}\n scope={pickerDialog?.scope}\n onClose={() => {\n setPickerDialog(null);\n }}\n onSelectId={(id) => {\n if (pickerDialog == null) {\n return;\n }\n if (pickerDialog.mode === 'list') {\n const currentIds = pickerDialog.currentIds ?? [];\n const nextIds = currentIds.includes(id)\n ? currentIds\n : [...currentIds, id];\n const nextWhere = setWhereValue(\n state.where,\n pickerDialog.whereKey,\n nextIds,\n pickerDialog.path,\n );\n setIsFilterDrawerOpen(true);\n pushState({ ...state, where: nextWhere });\n return;\n }\n const nextWhere = setWhereValue(\n state.where,\n pickerDialog.whereKey,\n id,\n pickerDialog.path,\n );\n setIsFilterDrawerOpen(true);\n pushState({ ...state, where: nextWhere });\n }}\n />\n </div>\n );\n\n const shouldRenderTableFooter =\n rows.length > 0 || isLoadingMore || hasNextPage;\n\n const tableFooterNode = shouldRenderTableFooter ? (\n <>\n <BackofficeListFooter\n mode=\"status\"\n loadedCount={rows.length}\n totalCount={totalCount}\n hasNextPage={hasNextPage}\n isLoading={isLoadingMore}\n pageInfoState={\n hasInconsistentPageInfo\n ? 'inconsistent'\n : isLoadingMore\n ? 'loading'\n : hasNextPage\n ? 'ready'\n : 'complete'\n }\n labels={{\n loaded: tableFooterMeta,\n loading: t('list.loadMore.loading'),\n end: t('list.loadMore.end'),\n }}\n />\n </>\n ) : null;\n\n if (variant === 'embedded') {\n return (\n <BackofficeListFilterProvider\n config={config}\n state={state}\n pushState={pushState}\n >\n <div className={styles.embeddedContainer}>\n <div className={styles.embeddedHeader}>{headerTitle}</div>\n {filtersBarNode}\n {statusBanner}\n {tableNode}\n {tableFooterNode}\n </div>\n </BackofficeListFilterProvider>\n );\n }\n\n return (\n <BackofficeListFilterProvider\n config={config}\n state={state}\n pushState={pushState}\n >\n <ListPageTemplate\n headerNode={\n <BackofficePageHeader\n title={headerTitle}\n subtitle={headerSubtitle}\n actions={headerActions}\n />\n }\n toolbarNode={filtersBarNode}\n statusNode={statusBanner}\n tableNode={tableNode}\n tableFooterNode={tableFooterNode}\n presentation=\"flat\"\n bodyScrollMode={BACKOFFICE_LIST_BODY_SCROLL_MODE}\n />\n </BackofficeListFilterProvider>\n );\n};\n\nexport default BackofficeEntityListScaffold;\n"],"mappings":"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"}
@@ -1,4 +1,3 @@
1
- /* empty css */
2
1
  //#region src/components/backoffice/scaffolds/backofficeEntityListScaffold.css.ts
3
2
  var e = "txvbqbfpn txvbqbh7g txvbqbey txvbqbhdl", t = "txvbqb19qg txvbqb19uy txvbqbu4k", n = "txvbqbfpn txvbqbh4x txvbqbhdl txvbqb19us", r = "txvbqbfpn txvbqbh7g txvbqbey txvbqbhd8 txvbqbv7x", i = "txvbqbfpn txvbqbh4x txvbqbhdy", a = "txvbqbfpn txvbqbh4x txvbqbjzu txvbqbu86", o = "txvbqb10mx txvbqb11ki txvbqb12hq txvbqbxtt txvbqbfpn txvbqbey txvbqbhdl txvbqbge txvbqbp66 txvbqb29r txvbqb2sj txvbqb1d9 txvbqb2tz txvbqb1b8p txvbqb1bgt txvbqb9j txvbqbo4z", s = "txvbqb9w txvbqbhbf txvbqb1bgr";
4
3
  //#endregion
@@ -1,4 +1,3 @@
1
- /* empty css */
2
1
  //#region src/components/backoffice/scaffolds/backofficeTabbedDetailShell.css.ts
3
2
  var e = "txvbqbfpn", t = "txvbqbfpn txvbqbh4x txvbqbheb";
4
3
  //#endregion
@@ -1,4 +1,3 @@
1
- /* empty css */
2
1
  /* empty css */
3
2
  import { c as e } from "../../../node_modules/@vanilla-extract/recipes/dist/createRuntimeFn-62c9670f.esm.js";
4
3
  //#region src/components/backoffice/shared/backofficeFilterableCell.css.ts
@@ -1,4 +1,3 @@
1
- /* empty css */
2
1
  //#region src/components/backoffice/shared/backofficeInlineFilterRow.css.ts
3
2
  var e = "txvbqbfqq txvbqbey txvbqbhd8 txvbqbh73 txvbqbu4k txvbqbv7x txvbqbwr6", t = "txvbqbfqq txvbqbey txvbqbls4 txvbqbh6d", n = "txvbqbv7x txvbqbu4k txvbqbwr6 txvbqb18es txvbqb1awp";
4
3
  //#endregion
@@ -1,4 +1,3 @@
1
- /* empty css */
2
1
  //#region src/components/backoffice/tools/backofficeToolsForm.css.ts
3
2
  var e = "txvbqbfpn txvbqbh4x txvbqbhdy", t = "txvbqbfpn txvbqblsh txvbqbltl", n = "txvbqbfpn txvbqbey txvbqblt7 txvbqbh7g txvbqbhdl", r = "txvbqbfpn txvbqbh4x txvbqbhdy", i = "txvbqbfq0 txvbqbheb txvbqbjdg", a = "txvbqb12j6 txvbqbxv9 txvbqbfpn txvbqbls4";
4
3
  //#endregion
@@ -1,4 +1,3 @@
1
- /* empty css */
2
1
  //#region src/components/backoffice/tools/backofficeToolsJsonForm.css.ts
3
2
  var e = "txvbqbfpn txvbqbh4x txvbqbheb", t = "txvbqbfpn txvbqblsh txvbqbltl", n = "txvbqbfpn txvbqbey txvbqblt7 txvbqbh7g txvbqbhdl";
4
3
  //#endregion
@@ -1,7 +1,7 @@
1
1
  //#region src/filters/filterHelpers.ts
2
2
  var e = (e, t) => {
3
3
  let n = e ?? [], r = t ?? [];
4
- return n.length === r.length ? n.every((e, t) => e === r[t]) : !1;
4
+ return n.length === r.length && n.every((e, t) => e === r[t]);
5
5
  };
6
6
  function t(t, n, r) {
7
7
  let { filters: i } = t.list;
@@ -1 +1 @@
1
- {"version":3,"file":"filterHelpers.js","names":[],"sources":["../../../src/filters/filterHelpers.ts"],"sourcesContent":["import type {\n BackofficeFilterSpec,\n BackofficeRuntimeResolvedListFacetConfig,\n} from '@plumile/backoffice-core/types.js';\n\n/** Compare two optional path arrays for equality. */\nconst arePathsEqual = (\n left?: readonly string[],\n right?: readonly string[],\n): boolean => {\n const leftPath = left ?? [];\n const rightPath = right ?? [];\n if (leftPath.length !== rightPath.length) {\n return false;\n }\n return leftPath.every((segment, index) => {\n return segment === rightPath[index];\n });\n};\n\n/** Find a filter spec by its where key and optional path. */\nexport function resolveFilterForWhereKey(\n config: BackofficeRuntimeResolvedListFacetConfig,\n whereKey: string,\n path?: readonly string[],\n): BackofficeFilterSpec<Record<string, unknown>> | null {\n const { filters } = config.list;\n const match = filters.find((filter) => {\n return (\n String(filter.whereKey ?? filter.id) === whereKey &&\n arePathsEqual(filter.path, path)\n );\n });\n return match ?? null;\n}\n\n/** Resolve a filter spec from a column id, alias, or contains field. */\nexport function resolveFilterForColumn(\n config: BackofficeRuntimeResolvedListFacetConfig,\n columnId: string,\n columnAliases?: Record<string, string>,\n): BackofficeFilterSpec<Record<string, unknown>> | null {\n const direct = resolveFilterForWhereKey(config, columnId);\n if (direct != null) {\n return direct;\n }\n\n const { [columnId]: alias } = columnAliases ?? {};\n if (alias != null) {\n const aliasFilter = resolveFilterForWhereKey(config, alias);\n if (aliasFilter != null) {\n return aliasFilter;\n }\n }\n\n const containsKey = `${columnId}Contains`;\n const containsFilter = resolveFilterForWhereKey(config, containsKey);\n if (containsFilter != null) {\n return containsFilter;\n }\n\n return null;\n}\n\n/** Check if a value is compatible with a filter spec. */\nexport function canFilterValue<Where extends Record<string, unknown>>(\n filter: BackofficeFilterSpec<Where>,\n value: unknown,\n): boolean {\n if (value == null) {\n return false;\n }\n\n if (filter.kind === 'boolean') {\n return typeof value === 'boolean';\n }\n\n if (filter.kind === 'entityId') {\n return typeof value === 'string' && value.trim() !== '';\n }\n\n if (filter.kind === 'number') {\n return typeof value === 'number' && Number.isFinite(value);\n }\n\n if (filter.kind === 'datetime') {\n return typeof value === 'string' && value.trim() !== '';\n }\n\n if (filter.kind === 'stringList') {\n if (typeof value === 'string') {\n return value.trim() !== '';\n }\n return (\n Array.isArray(value) &&\n value.some((entry) => {\n return typeof entry === 'string' && entry.trim() !== '';\n })\n );\n }\n\n if (typeof value === 'number') {\n return false;\n }\n\n if (typeof value !== 'string') {\n return false;\n }\n\n return value.trim() !== '';\n}\n"],"mappings":";AAMA,IAAM,KACJ,GACA,MACY;CACZ,IAAM,IAAW,KAAQ,CAAC,GACpB,IAAY,KAAS,CAAC;CAI5B,OAHI,EAAS,WAAW,EAAU,SAG3B,EAAS,OAAO,GAAS,MACvB,MAAY,EAAU,EAC9B,IAJQ;AAKX;AAGA,SAAgB,EACd,GACA,GACA,GACsD;CACtD,IAAM,EAAE,eAAY,EAAO;CAO3B,OANc,EAAQ,MAAM,MAExB,OAAO,EAAO,YAAY,EAAO,EAAE,MAAM,KACzC,EAAc,EAAO,MAAM,CAAI,CAG5B,KAAS;AAClB;AAGA,SAAgB,EACd,GACA,GACA,GACsD;CACtD,IAAM,IAAS,EAAyB,GAAQ,CAAQ;CACxD,IAAI,KAAU,MACZ,OAAO;CAGT,IAAM,GAAG,IAAW,MAAU,KAAiB,CAAC;CAChD,IAAI,KAAS,MAAM;EACjB,IAAM,IAAc,EAAyB,GAAQ,CAAK;EAC1D,IAAI,KAAe,MACjB,OAAO;CAEX;CAQA,OALuB,EAAyB,GAAQ,GADjC,EAAS,SAE5B,KAIG;AACT;AAGA,SAAgB,EACd,GACA,GACS;CAyCT,OAxCI,KAAS,OACJ,KAGL,EAAO,SAAS,YACX,OAAO,KAAU,YAGtB,EAAO,SAAS,aACX,OAAO,KAAU,YAAY,EAAM,KAAK,MAAM,KAGnD,EAAO,SAAS,WACX,OAAO,KAAU,YAAY,OAAO,SAAS,CAAK,IAGvD,EAAO,SAAS,aACX,OAAO,KAAU,YAAY,EAAM,KAAK,MAAM,KAGnD,EAAO,SAAS,eACd,OAAO,KAAU,WACZ,EAAM,KAAK,MAAM,KAGxB,MAAM,QAAQ,CAAK,KACnB,EAAM,MAAM,MACH,OAAO,KAAU,YAAY,EAAM,KAAK,MAAM,EACtD,IAID,OAAO,KAAU,YAIjB,OAAO,KAAU,WACZ,KAGF,EAAM,KAAK,MAAM;AAC1B"}
1
+ {"version":3,"file":"filterHelpers.js","names":[],"sources":["../../../src/filters/filterHelpers.ts"],"sourcesContent":["import type {\n BackofficeFilterSpec,\n BackofficeRuntimeResolvedListFacetConfig,\n} from '@plumile/backoffice-core/types.js';\n\n/** Compare two optional path arrays for equality. */\nconst arePathsEqual = (\n left?: readonly string[],\n right?: readonly string[],\n): boolean => {\n const leftPath = left ?? [];\n const rightPath = right ?? [];\n if (leftPath.length !== rightPath.length) {\n return false;\n }\n return leftPath.every((segment, index) => {\n return segment === rightPath[index];\n });\n};\n\n/** Find a filter spec by its where key and optional path. */\nexport function resolveFilterForWhereKey(\n config: BackofficeRuntimeResolvedListFacetConfig,\n whereKey: string,\n path?: readonly string[],\n): BackofficeFilterSpec<Record<string, unknown>> | null {\n const { filters } = config.list;\n const match = filters.find((filter) => {\n return (\n String(filter.whereKey ?? filter.id) === whereKey &&\n arePathsEqual(filter.path, path)\n );\n });\n return match ?? null;\n}\n\n/** Resolve a filter spec from a column id, alias, or contains field. */\nexport function resolveFilterForColumn(\n config: BackofficeRuntimeResolvedListFacetConfig,\n columnId: string,\n columnAliases?: Record<string, string>,\n): BackofficeFilterSpec<Record<string, unknown>> | null {\n const direct = resolveFilterForWhereKey(config, columnId);\n if (direct != null) {\n return direct;\n }\n\n const { [columnId]: alias } = columnAliases ?? {};\n if (alias != null) {\n const aliasFilter = resolveFilterForWhereKey(config, alias);\n if (aliasFilter != null) {\n return aliasFilter;\n }\n }\n\n const containsKey = `${columnId}Contains`;\n const containsFilter = resolveFilterForWhereKey(config, containsKey);\n if (containsFilter != null) {\n return containsFilter;\n }\n\n return null;\n}\n\n/** Check if a value is compatible with a filter spec. */\nexport function canFilterValue<Where extends Record<string, unknown>>(\n filter: BackofficeFilterSpec<Where>,\n value: unknown,\n): boolean {\n if (value == null) {\n return false;\n }\n\n if (filter.kind === 'boolean') {\n return typeof value === 'boolean';\n }\n\n if (filter.kind === 'entityId') {\n return typeof value === 'string' && value.trim() !== '';\n }\n\n if (filter.kind === 'number') {\n return typeof value === 'number' && Number.isFinite(value);\n }\n\n if (filter.kind === 'datetime') {\n return typeof value === 'string' && value.trim() !== '';\n }\n\n if (filter.kind === 'stringList') {\n if (typeof value === 'string') {\n return value.trim() !== '';\n }\n return (\n Array.isArray(value) &&\n value.some((entry) => {\n return typeof entry === 'string' && entry.trim() !== '';\n })\n );\n }\n\n if (typeof value === 'number') {\n return false;\n }\n\n if (typeof value !== 'string') {\n return false;\n }\n\n return value.trim() !== '';\n}\n"],"mappings":";AAMA,IAAM,KACJ,GACA,MACY;CACZ,IAAM,IAAW,KAAQ,CAAC,GACpB,IAAY,KAAS,CAAC;CAI5B,OAHI,EAAS,WAAW,EAAU,UAG3B,EAAS,OAAO,GAAS,MACvB,MAAY,EAAU,EAC9B;AACH;AAGA,SAAgB,EACd,GACA,GACA,GACsD;CACtD,IAAM,EAAE,eAAY,EAAO;CAO3B,OANc,EAAQ,MAAM,MAExB,OAAO,EAAO,YAAY,EAAO,EAAE,MAAM,KACzC,EAAc,EAAO,MAAM,CAAI,CAG5B,KAAS;AAClB;AAGA,SAAgB,EACd,GACA,GACA,GACsD;CACtD,IAAM,IAAS,EAAyB,GAAQ,CAAQ;CACxD,IAAI,KAAU,MACZ,OAAO;CAGT,IAAM,GAAG,IAAW,MAAU,KAAiB,CAAC;CAChD,IAAI,KAAS,MAAM;EACjB,IAAM,IAAc,EAAyB,GAAQ,CAAK;EAC1D,IAAI,KAAe,MACjB,OAAO;CAEX;CAQA,OALuB,EAAyB,GAAQ,GADjC,EAAS,SAE5B,KAIG;AACT;AAGA,SAAgB,EACd,GACA,GACS;CAyCT,OAxCI,KAAS,OACJ,KAGL,EAAO,SAAS,YACX,OAAO,KAAU,YAGtB,EAAO,SAAS,aACX,OAAO,KAAU,YAAY,EAAM,KAAK,MAAM,KAGnD,EAAO,SAAS,WACX,OAAO,KAAU,YAAY,OAAO,SAAS,CAAK,IAGvD,EAAO,SAAS,aACX,OAAO,KAAU,YAAY,EAAM,KAAK,MAAM,KAGnD,EAAO,SAAS,eACd,OAAO,KAAU,WACZ,EAAM,KAAK,MAAM,KAGxB,MAAM,QAAQ,CAAK,KACnB,EAAM,MAAM,MACH,OAAO,KAAU,YAAY,EAAM,KAAK,MAAM,EACtD,IAID,OAAO,KAAU,YAIjB,OAAO,KAAU,WACZ,KAGF,EAAM,KAAK,MAAM;AAC1B"}
@@ -45,7 +45,8 @@ var i = "backoffice.sidebar.pins.v1", a = (e) => {
45
45
  m([]);
46
46
  return;
47
47
  }
48
- m(o(a(u), f));
48
+ let e = a(u);
49
+ m(o(e, f));
49
50
  }, [
50
51
  l,
51
52
  u,
@@ -1 +1 @@
1
- {"version":3,"file":"useBackofficeSidebarPins.js","names":[],"sources":["../../../src/hooks/useBackofficeSidebarPins.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useState } from 'react';\n\nconst DEFAULT_STORAGE_KEY = 'backoffice.sidebar.pins.v1';\n\ntype PinsPayload = unknown;\n\nconst readPinsFromStorage = (storageKey: string): string[] => {\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 PinsPayload;\n if (!Array.isArray(parsed)) {\n return [];\n }\n return parsed.filter((entry): entry is string => {\n return typeof entry === 'string';\n });\n } catch {\n return [];\n }\n};\n\nconst normalizePins = (\n pins: readonly string[],\n validIds: Set<string>,\n): string[] => {\n const output: string[] = [];\n const seen = new Set<string>();\n pins.forEach((entry) => {\n if (!validIds.has(entry)) {\n return;\n }\n if (seen.has(entry)) {\n return;\n }\n seen.add(entry);\n output.push(entry);\n });\n return output;\n};\n\nconst reorderPins = (\n pins: readonly string[],\n fromId: string,\n toId: string,\n): readonly string[] => {\n if (fromId === toId) {\n return pins;\n }\n const fromIndex = pins.indexOf(fromId);\n const toIndex = pins.indexOf(toId);\n if (fromIndex === -1 || toIndex === -1 || fromIndex === toIndex) {\n return pins;\n }\n const next = [...pins];\n next.splice(fromIndex, 1);\n next.splice(toIndex, 0, fromId);\n return next;\n};\n\nexport type SidebarPinsState = {\n pins: readonly string[];\n isPinned: (id: string) => boolean;\n pin: (id: string) => void;\n unpin: (id: string) => void;\n toggle: (id: string) => void;\n reorder: (fromId: string, toId: string) => void;\n};\n\nexport type UseBackofficeSidebarPinsInput = {\n enabled?: boolean;\n storageKey?: string;\n visibleEntityIds: readonly string[];\n};\n\nexport const useBackofficeSidebarPins = (\n input: UseBackofficeSidebarPinsInput,\n): SidebarPinsState => {\n const {\n enabled = true,\n storageKey = DEFAULT_STORAGE_KEY,\n visibleEntityIds,\n } = input;\n const validIds = useMemo(() => {\n return new Set(visibleEntityIds);\n }, [visibleEntityIds]);\n\n const [pins, setPins] = useState<string[]>(() => {\n if (!enabled) {\n return [];\n }\n const stored = readPinsFromStorage(storageKey);\n return normalizePins(stored, validIds);\n });\n\n useEffect(() => {\n if (!enabled) {\n setPins([]);\n return;\n }\n setPins((prev) => {\n const normalized = normalizePins(prev, validIds);\n if (normalized.length === prev.length) {\n let unchanged = true;\n for (let index = 0; index < normalized.length; index += 1) {\n if (normalized[index] !== prev[index]) {\n unchanged = false;\n break;\n }\n }\n if (unchanged) {\n return prev;\n }\n }\n return normalized;\n });\n }, [enabled, validIds]);\n\n useEffect(() => {\n if (!enabled) {\n setPins([]);\n return;\n }\n const stored = readPinsFromStorage(storageKey);\n setPins(normalizePins(stored, validIds));\n }, [enabled, storageKey, validIds]);\n\n useEffect(() => {\n if (!enabled || typeof window === 'undefined') {\n return;\n }\n try {\n window.localStorage.setItem(storageKey, JSON.stringify(pins));\n } catch {\n // Ignore storage errors in non-browser or restricted environments.\n }\n }, [enabled, pins, storageKey]);\n\n const pinsSet = useMemo(() => {\n return new Set(pins);\n }, [pins]);\n\n const pin = useCallback(\n (id: string) => {\n if (!enabled) {\n return;\n }\n if (!validIds.has(id)) {\n return;\n }\n setPins((prev) => {\n if (prev.includes(id)) {\n return prev;\n }\n return [...prev, id];\n });\n },\n [enabled, validIds],\n );\n\n const unpin = useCallback(\n (id: string) => {\n if (!enabled) {\n return;\n }\n setPins((prev) => {\n return prev.filter((entry) => {\n return entry !== id;\n });\n });\n },\n [enabled],\n );\n\n const toggle = useCallback(\n (id: string) => {\n if (pinsSet.has(id)) {\n unpin(id);\n } else {\n pin(id);\n }\n },\n [pin, pinsSet, unpin],\n );\n\n const reorder = useCallback(\n (fromId: string, toId: string) => {\n if (!enabled) {\n return;\n }\n setPins((prev) => {\n return reorderPins(prev, fromId, toId) as string[];\n });\n },\n [enabled],\n );\n\n const isPinned = useCallback(\n (id: string) => {\n return pinsSet.has(id);\n },\n [pinsSet],\n );\n\n return {\n pins,\n isPinned,\n pin,\n unpin,\n toggle,\n reorder,\n };\n};\n\nexport const __test = {\n normalizePins,\n readPinsFromStorage,\n reorderPins,\n};\n\nexport default useBackofficeSidebarPins;\n"],"mappings":"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"}
1
+ {"version":3,"file":"useBackofficeSidebarPins.js","names":[],"sources":["../../../src/hooks/useBackofficeSidebarPins.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useState } from 'react';\n\nconst DEFAULT_STORAGE_KEY = 'backoffice.sidebar.pins.v1';\n\ntype PinsPayload = unknown;\n\nconst readPinsFromStorage = (storageKey: string): string[] => {\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 PinsPayload;\n if (!Array.isArray(parsed)) {\n return [];\n }\n return parsed.filter((entry): entry is string => {\n return typeof entry === 'string';\n });\n } catch {\n return [];\n }\n};\n\nconst normalizePins = (\n pins: readonly string[],\n validIds: Set<string>,\n): string[] => {\n const output: string[] = [];\n const seen = new Set<string>();\n pins.forEach((entry) => {\n if (!validIds.has(entry)) {\n return;\n }\n if (seen.has(entry)) {\n return;\n }\n seen.add(entry);\n output.push(entry);\n });\n return output;\n};\n\nconst reorderPins = (\n pins: readonly string[],\n fromId: string,\n toId: string,\n): readonly string[] => {\n if (fromId === toId) {\n return pins;\n }\n const fromIndex = pins.indexOf(fromId);\n const toIndex = pins.indexOf(toId);\n if (fromIndex === -1 || toIndex === -1 || fromIndex === toIndex) {\n return pins;\n }\n const next = [...pins];\n next.splice(fromIndex, 1);\n next.splice(toIndex, 0, fromId);\n return next;\n};\n\nexport type SidebarPinsState = {\n pins: readonly string[];\n isPinned: (id: string) => boolean;\n pin: (id: string) => void;\n unpin: (id: string) => void;\n toggle: (id: string) => void;\n reorder: (fromId: string, toId: string) => void;\n};\n\nexport type UseBackofficeSidebarPinsInput = {\n enabled?: boolean;\n storageKey?: string;\n visibleEntityIds: readonly string[];\n};\n\nexport const useBackofficeSidebarPins = (\n input: UseBackofficeSidebarPinsInput,\n): SidebarPinsState => {\n const {\n enabled = true,\n storageKey = DEFAULT_STORAGE_KEY,\n visibleEntityIds,\n } = input;\n const validIds = useMemo(() => {\n return new Set(visibleEntityIds);\n }, [visibleEntityIds]);\n\n const [pins, setPins] = useState<string[]>(() => {\n if (!enabled) {\n return [];\n }\n const stored = readPinsFromStorage(storageKey);\n return normalizePins(stored, validIds);\n });\n\n useEffect(() => {\n if (!enabled) {\n setPins([]);\n return;\n }\n setPins((prev) => {\n const normalized = normalizePins(prev, validIds);\n if (normalized.length === prev.length) {\n let unchanged = true;\n for (let index = 0; index < normalized.length; index += 1) {\n if (normalized[index] !== prev[index]) {\n unchanged = false;\n break;\n }\n }\n if (unchanged) {\n return prev;\n }\n }\n return normalized;\n });\n }, [enabled, validIds]);\n\n useEffect(() => {\n if (!enabled) {\n setPins([]);\n return;\n }\n const stored = readPinsFromStorage(storageKey);\n setPins(normalizePins(stored, validIds));\n }, [enabled, storageKey, validIds]);\n\n useEffect(() => {\n if (!enabled || typeof window === 'undefined') {\n return;\n }\n try {\n window.localStorage.setItem(storageKey, JSON.stringify(pins));\n } catch {\n // Ignore storage errors in non-browser or restricted environments.\n }\n }, [enabled, pins, storageKey]);\n\n const pinsSet = useMemo(() => {\n return new Set(pins);\n }, [pins]);\n\n const pin = useCallback(\n (id: string) => {\n if (!enabled) {\n return;\n }\n if (!validIds.has(id)) {\n return;\n }\n setPins((prev) => {\n if (prev.includes(id)) {\n return prev;\n }\n return [...prev, id];\n });\n },\n [enabled, validIds],\n );\n\n const unpin = useCallback(\n (id: string) => {\n if (!enabled) {\n return;\n }\n setPins((prev) => {\n return prev.filter((entry) => {\n return entry !== id;\n });\n });\n },\n [enabled],\n );\n\n const toggle = useCallback(\n (id: string) => {\n if (pinsSet.has(id)) {\n unpin(id);\n } else {\n pin(id);\n }\n },\n [pin, pinsSet, unpin],\n );\n\n const reorder = useCallback(\n (fromId: string, toId: string) => {\n if (!enabled) {\n return;\n }\n setPins((prev) => {\n return reorderPins(prev, fromId, toId) as string[];\n });\n },\n [enabled],\n );\n\n const isPinned = useCallback(\n (id: string) => {\n return pinsSet.has(id);\n },\n [pinsSet],\n );\n\n return {\n pins,\n isPinned,\n pin,\n unpin,\n toggle,\n reorder,\n };\n};\n\nexport const __test = {\n normalizePins,\n readPinsFromStorage,\n reorderPins,\n};\n\nexport default useBackofficeSidebarPins;\n"],"mappings":"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"}