@plumile/backoffice-react 0.1.75 → 0.1.77

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 (74) hide show
  1. package/README.md +25 -0
  2. package/lib/esm/{AcceptInvitationScreen-CNLlSbdx.js → AcceptInvitationScreen-b2yaZeKV.js} +4 -4
  3. package/lib/esm/{AcceptInvitationScreen-CNLlSbdx.js.map → AcceptInvitationScreen-b2yaZeKV.js.map} +1 -1
  4. package/lib/esm/{AuthPanel-ttoH9YxE.js → AuthPanel-Co626p7A.js} +2 -2
  5. package/lib/esm/{AuthPanel-ttoH9YxE.js.map → AuthPanel-Co626p7A.js.map} +1 -1
  6. package/lib/esm/{BackofficeAcceptInvitationPage-DRxM1Z-U.js → BackofficeAcceptInvitationPage-BBHL6VvG.js} +7 -7
  7. package/lib/esm/{BackofficeAcceptInvitationPage-DRxM1Z-U.js.map → BackofficeAcceptInvitationPage-BBHL6VvG.js.map} +1 -1
  8. package/lib/esm/{sprinkles.css.ts.vanilla-n-NK_DwW.js → BackofficeConfigContext-R0t1owTI.js} +1 -1
  9. package/lib/esm/BackofficeConfigContext-R0t1owTI.js.map +1 -0
  10. package/lib/esm/{BackofficeDashboardPage-GKyT60qb.js → BackofficeDashboardPage-B5_YC1ZL.js} +5 -5
  11. package/lib/esm/BackofficeDashboardPage-B5_YC1ZL.js.map +1 -0
  12. package/lib/esm/{BackofficeDetailPayload-B-qs8Fai.js → BackofficeDetailPayload-CbsZKnw6.js} +10 -10
  13. package/lib/esm/BackofficeDetailPayload-CbsZKnw6.js.map +1 -0
  14. package/lib/esm/{BackofficeEntityActionFormDialog-FHlW0vys.js → BackofficeEntityActionFormDialog-BzKi1eyv.js} +19 -19
  15. package/lib/esm/BackofficeEntityActionFormDialog-BzKi1eyv.js.map +1 -0
  16. package/lib/esm/{BackofficeEntityDetailPage-CdrMXu5a.js → BackofficeEntityDetailPage-CE4tl5ZJ.js} +11 -11
  17. package/lib/esm/BackofficeEntityDetailPage-CE4tl5ZJ.js.map +1 -0
  18. package/lib/esm/{BackofficeEntityListPage-BxgqdFpL.js → BackofficeEntityListPage-CtLI15-L.js} +7 -7
  19. package/lib/esm/BackofficeEntityListPage-CtLI15-L.js.map +1 -0
  20. package/lib/esm/{BackofficeLayoutPage-k9OkLfXb.js → BackofficeLayoutPage-DpvTzwtK.js} +6 -6
  21. package/lib/esm/BackofficeLayoutPage-DpvTzwtK.js.map +1 -0
  22. package/lib/esm/{BackofficeLoginPage-C64BcxMw.js → BackofficeLoginPage-BeihjFO2.js} +8 -8
  23. package/lib/esm/{BackofficeLoginPage-C64BcxMw.js.map → BackofficeLoginPage-BeihjFO2.js.map} +1 -1
  24. package/lib/esm/{BackofficePasswordResetCompletePage-BA7kkUxN.js → BackofficePasswordResetCompletePage-CkaMaFNT.js} +6 -6
  25. package/lib/esm/{BackofficePasswordResetCompletePage-BA7kkUxN.js.map → BackofficePasswordResetCompletePage-CkaMaFNT.js.map} +1 -1
  26. package/lib/esm/{BackofficePasswordResetRequestPage-B9wSZcyn.js → BackofficePasswordResetRequestPage-Df8mcLkC.js} +6 -6
  27. package/lib/esm/{BackofficePasswordResetRequestPage-B9wSZcyn.js.map → BackofficePasswordResetRequestPage-Df8mcLkC.js.map} +1 -1
  28. package/lib/esm/{BackofficeRightPageLayout-ktdlvTZJ.js → BackofficeRightPageLayout-D7QRE8KZ.js} +3 -3
  29. package/lib/esm/BackofficeRightPageLayout-D7QRE8KZ.js.map +1 -0
  30. package/lib/esm/{BackofficeVerifyEmailPage-CAzMqo2K.js → BackofficeVerifyEmailPage-CE_6-wGN.js} +5 -5
  31. package/lib/esm/{BackofficeVerifyEmailPage-CAzMqo2K.js.map → BackofficeVerifyEmailPage-CE_6-wGN.js.map} +1 -1
  32. package/lib/esm/{EntityFilterValue-SC_jkj4O.js → EntityFilterValue-Bn9VGr2M.js} +2 -2
  33. package/lib/esm/{EntityFilterValue-SC_jkj4O.js.map → EntityFilterValue-Bn9VGr2M.js.map} +1 -1
  34. package/lib/esm/{EntityIdPickerDialog-FMC5Hx_I.js → EntityIdPickerDialog-D_qAlrU6.js} +4 -4
  35. package/lib/esm/EntityIdPickerDialog-D_qAlrU6.js.map +1 -0
  36. package/lib/esm/{LazyBackofficeEntityActionFormDialog-DOEgoIfT.js → LazyBackofficeEntityActionFormDialog-DndjG4kV.js} +5 -5
  37. package/lib/esm/LazyBackofficeEntityActionFormDialog-DndjG4kV.js.map +1 -0
  38. package/lib/esm/{PasswordResetCompleteScreen-C4GQdavL.js → PasswordResetCompleteScreen-CWxk9AWl.js} +3 -3
  39. package/lib/esm/{PasswordResetCompleteScreen-C4GQdavL.js.map → PasswordResetCompleteScreen-CWxk9AWl.js.map} +1 -1
  40. package/lib/esm/{PasswordResetRequestScreen-aUY_yDqM.js → PasswordResetRequestScreen-DBIHOmsl.js} +3 -3
  41. package/lib/esm/{PasswordResetRequestScreen-aUY_yDqM.js.map → PasswordResetRequestScreen-DBIHOmsl.js.map} +1 -1
  42. package/lib/esm/{VerifyEmailScreen-2DuHJgdY.js → VerifyEmailScreen-CUOEwmf1.js} +2 -2
  43. package/lib/esm/{VerifyEmailScreen-2DuHJgdY.js.map → VerifyEmailScreen-CUOEwmf1.js.map} +1 -1
  44. package/lib/esm/backoffice-react.js +21 -21
  45. package/lib/esm/backoffice-react.js.map +1 -1
  46. package/lib/esm/loginPage.css-4M4PrzUn.js +12 -0
  47. package/lib/esm/loginPage.css-4M4PrzUn.js.map +1 -0
  48. package/lib/esm/style.css +1 -1
  49. package/lib/esm/{synchronizeAuthStatusQuery-lLR0XFew.js → synchronizeAuthStatusQuery-Ba776lwa.js} +4 -4
  50. package/lib/esm/{synchronizeAuthStatusQuery-lLR0XFew.js.map → synchronizeAuthStatusQuery-Ba776lwa.js.map} +1 -1
  51. package/lib/esm/{useAuth-AczFS-oL.js → useAuth-DzWJXJ_9.js} +2 -2
  52. package/lib/esm/{useAuth-AczFS-oL.js.map → useAuth-DzWJXJ_9.js.map} +1 -1
  53. package/lib/esm/{useBackofficeAuth-BHteJQzA.js → useBackofficeAuth-L9k9i9BI.js} +3 -3
  54. package/lib/esm/{useBackofficeAuth-BHteJQzA.js.map → useBackofficeAuth-L9k9i9BI.js.map} +1 -1
  55. package/lib/esm/{useBackofficeLazyValue-B0-ckL6e.js → useBackofficeLazyValue-Dnii1_dE.js} +2 -2
  56. package/lib/esm/{useBackofficeLazyValue-B0-ckL6e.js.map → useBackofficeLazyValue-Dnii1_dE.js.map} +1 -1
  57. package/lib/types/auth/login/loginPage.css.d.ts.map +1 -1
  58. package/lib/types/components/backoffice/detail/backofficeDetailRelationLink.css.d.ts.map +1 -1
  59. package/lib/types/components/backoffice/filters/backofficeFilterAction.css.d.ts.map +1 -1
  60. package/lib/types/components/backoffice/layout/backofficeSidebarActions.css.d.ts.map +1 -1
  61. package/lib/types/components/backoffice/routing/backofficeRoutePendingBar.css.d.ts.map +1 -1
  62. package/package.json +5 -5
  63. package/lib/esm/BackofficeDashboardPage-GKyT60qb.js.map +0 -1
  64. package/lib/esm/BackofficeDetailPayload-B-qs8Fai.js.map +0 -1
  65. package/lib/esm/BackofficeEntityActionFormDialog-FHlW0vys.js.map +0 -1
  66. package/lib/esm/BackofficeEntityDetailPage-CdrMXu5a.js.map +0 -1
  67. package/lib/esm/BackofficeEntityListPage-BxgqdFpL.js.map +0 -1
  68. package/lib/esm/BackofficeLayoutPage-k9OkLfXb.js.map +0 -1
  69. package/lib/esm/BackofficeRightPageLayout-ktdlvTZJ.js.map +0 -1
  70. package/lib/esm/EntityIdPickerDialog-FMC5Hx_I.js.map +0 -1
  71. package/lib/esm/LazyBackofficeEntityActionFormDialog-DOEgoIfT.js.map +0 -1
  72. package/lib/esm/loginPage.css-BDQJNcSr.js +0 -12
  73. package/lib/esm/loginPage.css-BDQJNcSr.js.map +0 -1
  74. package/lib/esm/sprinkles.css.ts.vanilla-n-NK_DwW.js.map +0 -1
@@ -1,17 +1,17 @@
1
1
  import { t as e } from "./useRelayEnvironment-vQ86aW-n.js";
2
- import { n as t } from "./sprinkles.css.ts.vanilla-n-NK_DwW.js";
2
+ import { n as t } from "./BackofficeConfigContext-R0t1owTI.js";
3
3
  import { n, t as r } from "./useBackofficeReactTranslation-WfXU8kCf.js";
4
- import "./EntityFilterValue-SC_jkj4O.js";
5
- import { n as i } from "./EntityIdPickerDialog-FMC5Hx_I.js";
6
- import { a, n as o, r as s, t as c } from "./BackofficeDetailPayload-B-qs8Fai.js";
4
+ import "./EntityFilterValue-Bn9VGr2M.js";
5
+ import { n as i } from "./EntityIdPickerDialog-D_qAlrU6.js";
6
+ import { a, n as o, r as s, t as c } from "./BackofficeDetailPayload-CbsZKnw6.js";
7
7
  import { i as l } from "./mutationResult-CcQMY13J.js";
8
8
  import { t as u } from "./pageResolution-hAQA5C6S.js";
9
- import { n as d, t as f } from "./BackofficeRightPageLayout-ktdlvTZJ.js";
9
+ import { n as d, t as f } from "./BackofficeRightPageLayout-D7QRE8KZ.js";
10
10
  import "./BackofficeTopbarPortalContext-iD7dm4_h.js";
11
11
  import { n as p, t as m } from "./toastViewAction-BGTS7vqm.js";
12
12
  import { n as h } from "./buildBreadcrumbs-CqF9Nh6x.js";
13
13
  import { n as g } from "./BackofficeEntityDetailLayoutContext-C_tBqkVq.js";
14
- import { i as ee, n as _, r as v, t as y } from "./LazyBackofficeEntityActionFormDialog-DOEgoIfT.js";
14
+ import { i as ee, n as _, r as v, t as y } from "./LazyBackofficeEntityActionFormDialog-DndjG4kV.js";
15
15
  import { Suspense as b, useCallback as x, useContext as S, useMemo as C, useState as w } from "react";
16
16
  import { useTranslation as T } from "react-i18next";
17
17
  import { HttpRedirect as E, Link as D, RoutingContext as O } from "@plumile/router";
@@ -26,7 +26,7 @@ import { setWhereValue as Ce } from "@plumile/backoffice-core/filters/where.js";
26
26
  var we = ({ node: e, render: t, notFound: n }) => {
27
27
  let { t: i } = r(), a = n ?? i("detail.notFound");
28
28
  return e == null ? /* @__PURE__ */ q(K, { children: a }) : t(e) ?? /* @__PURE__ */ q(K, { children: a });
29
- }, Te = "_1lzrtns0 vncd899io vncd89co vncd89ao6", Ee = "_1lzrtns2 _1lzrtns1 vncd899io vncd89co", De = "_1lzrtns3", Oe = ({ tone: e, icon: t, label: n }) => {
29
+ }, Te = "txvbqb9io txvbqbco txvbqbao6", Ee = "_1lzrtns0 txvbqb9io txvbqbco", De = "_1lzrtns1", Oe = ({ tone: e, icon: t, label: n }) => {
30
30
  let r = t != null, i = null;
31
31
  return r && (i = /* @__PURE__ */ q("span", {
32
32
  className: Ee,
@@ -41,7 +41,7 @@ var we = ({ node: e, render: t, notFound: n }) => {
41
41
  })]
42
42
  })
43
43
  });
44
- }, ke = "avdnn90 vncd899jf vncd89co vncd89ao6 vncd89ajx", Ae = "avdnn91 vncd899jf vncd89co vncd89anx", je = ({ tag: e, value: t }) => /* @__PURE__ */ J("span", {
44
+ }, ke = "txvbqb9jf txvbqbco txvbqbao6 txvbqbajx", Ae = "txvbqb9jf txvbqbco txvbqbanx", je = ({ tag: e, value: t }) => /* @__PURE__ */ J("span", {
45
45
  className: ke,
46
46
  children: [e != null && /* @__PURE__ */ q(G, {
47
47
  tone: e.tone,
@@ -50,7 +50,7 @@ var we = ({ node: e, render: t, notFound: n }) => {
50
50
  className: Ae,
51
51
  children: t
52
52
  })]
53
- }), Me = "_1tlv14d0 vncd899io vncd89ai6 vncd89aoo", Ne = "_1tlv14d1 vncd899io vncd89ai6 vncd89ao6 vncd89la6 vncd891rx", Pe = "_1tlv14d2 vncd891co vncd891qf vncd89wo vncd89v2v", Fe = "_1tlv14d3 vncd899io vncd89ai6 vncd89anx", Ie = "_1tlv14d4 vncd89al6 vncd898x vncd89v8t", Le = "_1tlv14d5 vncd89amo", Re = "_1tlv14d6 vncd898x", ze = ({ title: e, description: t, items: n }) => {
53
+ }), Me = "txvbqb9io txvbqbai6 txvbqbaoo", Ne = "txvbqb9io txvbqbai6 txvbqbao6 txvbqbla6 txvbqb1rx", Pe = "txvbqb1co txvbqb1qf txvbqbwo txvbqbv2v", Fe = "txvbqb9io txvbqbai6 txvbqbanx", Ie = "txvbqbal6 txvbqb8x txvbqbv8t", Le = "txvbqbamo", Re = "txvbqb8x", ze = ({ title: e, description: t, items: n }) => {
54
54
  let { t: i } = r();
55
55
  return n.length === 0 ? null : /* @__PURE__ */ q(s, {
56
56
  title: e,
@@ -172,7 +172,7 @@ var we = ({ node: e, render: t, notFound: n }) => {
172
172
  path: a
173
173
  })
174
174
  })
175
- }), Ge = "_1i6bm7z0 vncd899io vncd89co vncd89ao6 vncd89ajx", Ke = "_1i6bm7z1 vncd899io vncd89ai6 vncd89aof", qe = "_1i6bm7z2 vncd899io vncd89co vncd89ao6 vncd89ajx", Je = "_1i6bm7z3 vncd899io vncd89ai6 vncd89ao6";
175
+ }), Ge = "txvbqb9io txvbqbco txvbqbao6 txvbqbajx", Ke = "txvbqb9io txvbqbai6 txvbqbaof", qe = "txvbqb9io txvbqbco txvbqbao6 txvbqbajx", Je = "txvbqb9io txvbqbai6 txvbqbao6";
176
176
  //#endregion
177
177
  //#region src/i18n/useBackofficeFormats.ts
178
178
  function Ye() {
@@ -988,4 +988,4 @@ var Xe = (e) => e.pages.map((t) => ({
988
988
  //#endregion
989
989
  export { ft as BackofficeEntityDetailPage, ft as default };
990
990
 
991
- //# sourceMappingURL=BackofficeEntityDetailPage-CdrMXu5a.js.map
991
+ //# sourceMappingURL=BackofficeEntityDetailPage-CE4tl5ZJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BackofficeEntityDetailPage-CE4tl5ZJ.js","names":[],"sources":["../../src/components/backoffice/scaffolds/BackofficeEntityDetailScaffold.tsx","../../src/components/backoffice/detail/BackofficeDetailFlagTag.css.ts","../../src/components/backoffice/detail/BackofficeDetailFlagTag.tsx","../../src/components/backoffice/detail/backofficeDetailTaggedValue.css.ts","../../src/components/backoffice/detail/BackofficeDetailTaggedValue.tsx","../../src/components/backoffice/detail/backofficeDetailErrorList.css.ts","../../src/components/backoffice/detail/BackofficeDetailErrorList.tsx","../../src/components/backoffice/detail/BackofficeDetailRelationListBlock.tsx","../../src/pages/backofficeEntityDetailPage.css.ts","../../src/i18n/useBackofficeFormats.ts","../../src/pages/detail/buildTabsItems.ts","../../src/pages/BackofficeEntityDetailPage.tsx"],"sourcesContent":["import { type JSX, type ReactNode } from 'react';\n\nimport { useBackofficeReactTranslation } from '../../../i18n/useBackofficeReactTranslation.js';\n\nexport type BackofficeEntityDetailScaffoldProps<\n NodeUnion extends { __typename: string },\n> = {\n node: NodeUnion | null | undefined;\n render: (node: NodeUnion) => JSX.Element | null;\n notFound?: ReactNode;\n};\n\nexport const BackofficeEntityDetailScaffold = <\n NodeUnion extends { __typename: string },\n>({\n node,\n render,\n notFound,\n}: BackofficeEntityDetailScaffoldProps<NodeUnion>): JSX.Element => {\n const { t } = useBackofficeReactTranslation();\n const resolvedNotFound = notFound ?? t('detail.notFound');\n if (node == null) {\n return <>{resolvedNotFound}</>;\n }\n\n const content = render(node);\n if (content == null) {\n return <>{resolvedNotFound}</>;\n }\n\n return content;\n};\n\nexport default BackofficeEntityDetailScaffold;\n","import { style } from '@vanilla-extract/css';\n\nimport { sprinkles } from '@plumile/ui';\n\nexport const content = sprinkles({\n display: 'flex',\n alignItems: 'center',\n gap: 2,\n});\n\nexport const icon = style([\n sprinkles({\n display: 'flex',\n alignItems: 'center',\n }),\n {\n flex: '0 0 auto',\n },\n]);\n\nexport const label = style({\n flex: '0 1 auto',\n});\n","import { type JSX, type ReactNode } from 'react';\n\nimport { Tag, type TagTone } from '@plumile/ui';\n\nimport * as styles from './BackofficeDetailFlagTag.css.js';\n\nexport type BackofficeDetailFlagTagProps = {\n tone: TagTone;\n icon?: ReactNode;\n label: string;\n};\n\nexport const BackofficeDetailFlagTag = ({\n tone,\n icon,\n label,\n}: BackofficeDetailFlagTagProps): JSX.Element => {\n const hasIcon = icon != null;\n let iconNode: ReactNode | null = null;\n if (hasIcon) {\n iconNode = <span className={styles.icon}>{icon}</span>;\n }\n\n return (\n <Tag tone={tone}>\n <span className={styles.content}>\n {iconNode}\n <span className={styles.label}>{label}</span>\n </span>\n </Tag>\n );\n};\n\nexport default BackofficeDetailFlagTag;\n","import { sprinkles } from '@plumile/ui';\n\nexport const container = sprinkles({\n display: 'inline-flex',\n alignItems: 'center',\n gap: 2,\n flexWrap: 'wrap',\n});\n\nexport const value = sprinkles({\n display: 'inline-flex',\n alignItems: 'center',\n gap: 1,\n});\n","import { type JSX, type ReactNode } from 'react';\n\nimport type { BackofficeBadgeTone } from '@plumile/backoffice-core/types.js';\nimport { Tag } from '@plumile/ui';\n\nimport * as styles from './backofficeDetailTaggedValue.css.js';\n\nexport type BackofficeDetailTaggedValueProps = {\n tag: { label: string; tone?: BackofficeBadgeTone } | null;\n value: ReactNode;\n};\n\nexport const BackofficeDetailTaggedValue = ({\n tag,\n value,\n}: BackofficeDetailTaggedValueProps): JSX.Element => {\n return (\n <span className={styles.container}>\n {tag != null && <Tag tone={tag.tone}>{tag.label}</Tag>}\n <span className={styles.value}>{value}</span>\n </span>\n );\n};\n\nexport default BackofficeDetailTaggedValue;\n","import { sprinkles } from '@plumile/ui';\n\nexport const list = sprinkles({\n display: 'flex',\n flexDirection: 'column',\n gap: 4,\n});\n\nexport const item = sprinkles({\n display: 'flex',\n flexDirection: 'column',\n gap: 2,\n padding: 3,\n borderRadius: 'xl',\n});\n\nexport const itemSurface = sprinkles({\n borderWidth: 'default',\n borderStyle: 'solid',\n borderColor: 'borderSubtle',\n backgroundColor: 'surfaceMuted',\n});\n\nexport const header = sprinkles({\n display: 'flex',\n flexDirection: 'column',\n gap: 1,\n});\n\nexport const code = sprinkles({\n fontFamily: 'mono',\n fontSize: 'sm',\n color: 'textMuted',\n});\n\nexport const message = sprinkles({\n fontWeight: 'semibold',\n});\n\nexport const details = sprinkles({\n fontSize: 'sm',\n});\n","import { type JSX } from 'react';\n\nimport { LazyMarkdownRenderer, cx } from '@plumile/ui';\n\nimport { useBackofficeReactTranslation } from '../../../i18n/useBackofficeReactTranslation.js';\nimport { BackofficeDetailSection } from './BackofficeDetailSection.js';\nimport { formatJsonPayload } from './detailPayloadUtils.js';\n\nimport * as styles from './backofficeDetailErrorList.css.js';\n\nexport type BackofficeDetailErrorItem = {\n code: string;\n message: string;\n details?: unknown;\n};\n\nexport type BackofficeDetailErrorListProps = {\n title: string;\n description?: string;\n items: readonly BackofficeDetailErrorItem[];\n};\n\nexport const BackofficeDetailErrorList = ({\n title,\n description,\n items,\n}: BackofficeDetailErrorListProps): JSX.Element | null => {\n const { t } = useBackofficeReactTranslation();\n\n if (items.length === 0) {\n return null;\n }\n\n return (\n <BackofficeDetailSection title={title} description={description}>\n <div className={styles.list}>\n {items.map((error, index) => {\n let details = t('common.notAvailable');\n if (error.details != null) {\n details = formatJsonPayload(error.details);\n }\n return (\n <div\n key={`${error.code}-${index}`}\n className={cx(styles.item, styles.itemSurface)}\n >\n <div className={styles.header}>\n <span className={styles.code}>{error.code}</span>\n <span className={styles.message}>{error.message}</span>\n </div>\n <div className={styles.details}>\n <LazyMarkdownRenderer content={details} />\n </div>\n </div>\n );\n })}\n </div>\n </BackofficeDetailSection>\n );\n};\n\nexport default BackofficeDetailErrorList;\n","/* eslint-disable react-hooks/rules-of-hooks */\nimport { Suspense, useCallback, useMemo, useState, type JSX } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport * as ReactRelay from 'react-relay';\nimport type { OperationType } from 'relay-runtime';\n\nimport {\n BACKOFFICE_LIST_REFETCH_POLICY,\n BACKOFFICE_RELATED_TAB_PAGE_SIZE,\n} from '@plumile/backoffice-core/constants.js';\nimport { setWhereValue } from '@plumile/backoffice-core/filters/where.js';\nimport type {\n BackofficeListState,\n BackofficeResolvedListFacetConfig,\n} from '@plumile/backoffice-core/types.js';\nimport { BackofficeTableSkeleton } from '@plumile/ui';\n\nimport { buildDataTableColumns } from '../columns/buildDataTableColumns.js';\nimport { useBackofficeLoadMore } from '../../../hooks/useBackofficeLoadMore.js';\nimport { useBackofficeListRefetch } from '../../../hooks/useBackofficeListRefetch.js';\nimport { useBackofficeReactTranslation } from '../../../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeConfig } from '../../../provider/BackofficeConfigContext.js';\nimport { useBackofficeListEntitiesLoader } from '../../../provider/useBackofficeEntityLoader.js';\nimport { BackofficeEntityListScaffold } from '../scaffolds/BackofficeEntityListScaffold.js';\nimport { BackofficeErrorBoundary } from '../errors/BackofficeErrorBoundary.js';\n\nconst { useLazyLoadQuery, usePaginationFragment } = ReactRelay;\n\nexport type BackofficeDetailRelationListBlockProps = {\n title: string;\n target: string;\n whereKey: string;\n value: string | null;\n path?: readonly string[];\n};\n\ntype RelationListContentProps = {\n title: string;\n config: BackofficeResolvedListFacetConfig;\n entities: ReturnType<typeof useBackofficeConfig>['entities'];\n whereKey: string;\n value: string | null;\n path?: readonly string[];\n};\n\ntype RelationListBlockBodyProps = {\n title: string;\n targetId: string;\n whereKey: string;\n value: string | null;\n path?: readonly string[];\n};\n\nconst RelationListContent = ({\n title,\n config,\n entities,\n whereKey,\n value,\n path,\n}: RelationListContentProps): JSX.Element | null => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n if (config.list.kind === 'records') {\n return null;\n }\n const listConfig = config.list;\n const listDefaults = config.listDefaults ??\n listConfig.defaultState ?? { where: null, sort: null };\n\n const [state, setState] = useState<BackofficeListState<unknown, string>>({\n where: listDefaults.where as never,\n sort: listDefaults.sort ?? null,\n });\n\n const relationWhere = useMemo(() => {\n if (value == null || value.trim() === '') {\n return null;\n }\n return setWhereValue(\n state.where as Record<string, unknown> | null,\n whereKey as never,\n value,\n path,\n );\n }, [path, state.where, value, whereKey]);\n\n const effectiveWhere = relationWhere ?? (state.where as never);\n const resolvedSort = state.sort ?? listDefaults.sort;\n const variablesBase = useMemo(() => {\n return {\n where: effectiveWhere as never,\n sort: resolvedSort as never,\n count: BACKOFFICE_RELATED_TAB_PAGE_SIZE,\n cursor: null,\n };\n }, [effectiveWhere, resolvedSort]);\n\n const variables = useMemo(() => {\n if (listConfig.buildVariables != null) {\n return listConfig.buildVariables(variablesBase as never);\n }\n return variablesBase;\n }, [listConfig, variablesBase]);\n\n const queryData = useLazyLoadQuery<OperationType>(\n listConfig.query,\n variables as never,\n { fetchPolicy: 'store-or-network' },\n );\n\n const {\n data: fragmentData,\n loadNext,\n hasNext,\n isLoadingNext,\n refetch,\n } = usePaginationFragment(listConfig.fragment, queryData as never);\n\n const connection = listConfig.getConnection(fragmentData);\n const rows = useMemo(() => {\n return connection.edges.map((edge) => {\n return listConfig.toRow(edge.node);\n });\n }, [connection.edges, listConfig]);\n\n const columns = useMemo(() => {\n return buildDataTableColumns(listConfig.columns, {\n tApp,\n t,\n resolveEntityHref: (entityId, refId) => {\n const entityManifest = entities[entityId];\n if (entityManifest == null) {\n return null;\n }\n return entityManifest.routes.detail(refId);\n },\n });\n }, [entities, listConfig.columns, t, tApp]);\n\n const getRowId = useCallback(\n (row: unknown) => {\n return listConfig.getRowId(row as never);\n },\n [listConfig],\n );\n\n const defaults = useMemo(() => {\n const baseWhere = relationWhere ?? (listDefaults.where as never);\n return {\n where: baseWhere,\n sort: listDefaults.sort,\n count: BACKOFFICE_RELATED_TAB_PAGE_SIZE,\n cursor: null,\n };\n }, [listDefaults.sort, listDefaults.where, relationWhere]);\n\n const { onRefresh } = useBackofficeListRefetch({\n refetch: refetch as never,\n variables: variablesBase as never,\n defaults: defaults as never,\n fetchPolicy: BACKOFFICE_LIST_REFETCH_POLICY,\n buildVariables: listConfig.buildVariables as never,\n });\n\n const handleLoadMore = useBackofficeLoadMore({\n hasNext,\n isLoadingNext,\n loadNext,\n count: BACKOFFICE_RELATED_TAB_PAGE_SIZE,\n });\n\n return (\n <BackofficeEntityListScaffold\n config={config as never}\n state={state as never}\n pushState={(next) => {\n setState(next as never);\n }}\n header={{ title }}\n rows={rows}\n columns={columns as never}\n getRowId={getRowId}\n hasNextPage={hasNext}\n isLoadingMore={isLoadingNext}\n onLoadMore={handleLoadMore}\n onRefresh={onRefresh}\n totalCount={connection.totalCount ?? null}\n variant=\"embedded\"\n />\n );\n};\n\nconst RelationListBlockBody = ({\n title,\n targetId,\n whereKey,\n value,\n path,\n}: RelationListBlockBodyProps): JSX.Element | null => {\n const { entities } = useBackofficeConfig();\n const relatedEntityIds = useMemo(() => {\n return [targetId];\n }, [targetId]);\n const relatedEntitiesState =\n useBackofficeListEntitiesLoader(relatedEntityIds);\n\n if (relatedEntitiesState.status === 'loading') {\n return <BackofficeTableSkeleton rows={6} />;\n }\n\n if (relatedEntitiesState.status === 'error') {\n return null;\n }\n\n const config = relatedEntitiesState.modules[targetId]?.config;\n if (config == null) {\n return null;\n }\n\n return (\n <RelationListContent\n title={title}\n config={config}\n entities={entities}\n whereKey={whereKey}\n value={value}\n path={path}\n />\n );\n};\n\nexport const BackofficeDetailRelationListBlock = ({\n title,\n target,\n whereKey,\n value,\n path,\n}: BackofficeDetailRelationListBlockProps): JSX.Element => {\n return (\n <BackofficeErrorBoundary\n fallback={() => {\n return <BackofficeTableSkeleton rows={6} />;\n }}\n >\n <Suspense fallback={<BackofficeTableSkeleton rows={6} />}>\n <RelationListBlockBody\n title={title}\n targetId={target}\n whereKey={whereKey}\n value={value}\n path={path}\n />\n </Suspense>\n </BackofficeErrorBoundary>\n );\n};\n\nexport default BackofficeDetailRelationListBlock;\n","import { sprinkles } from '@plumile/ui';\n\nexport const headerActions = sprinkles({\n display: 'flex',\n alignItems: 'center',\n gap: 2,\n flexWrap: 'wrap',\n});\n\nexport const headerBlock = sprinkles({\n display: 'flex',\n flexDirection: 'column',\n gap: 3,\n});\n\nexport const headerMeta = sprinkles({\n display: 'flex',\n alignItems: 'center',\n gap: 2,\n flexWrap: 'wrap',\n});\n\nexport const headerMetaList = sprinkles({\n display: 'flex',\n flexDirection: 'column',\n gap: 2,\n});\n","import { useBackofficeReactTranslation } from './useBackofficeReactTranslation.js';\n\nexport type BackofficeFormats = {\n formatNumber: (value: number | null | undefined) => string;\n formatCurrency: (value: number | null | undefined) => string;\n formatPercent: (value: number | null | undefined) => string;\n};\n\n/**\n *\n */\nexport function useBackofficeFormats(): BackofficeFormats {\n const { t } = useBackofficeReactTranslation();\n\n /**\n *\n */\n function formatNumber(value: number | null | undefined): string {\n return t('format.number', { value });\n }\n\n /**\n *\n */\n function formatCurrency(value: number | null | undefined): string {\n return t('format.currency', { value });\n }\n\n /**\n *\n */\n function formatPercent(value: number | null | undefined): string {\n return t('format.percent', { value });\n }\n\n return { formatNumber, formatCurrency, formatPercent };\n}\n","import type { BackofficeDetailPageRouteSpec } from '@plumile/backoffice-core/types.js';\nimport type { BackofficeTabItem } from '@plumile/ui';\nimport type { TFunction } from 'i18next';\n\ntype DetailPage<Node> = BackofficeDetailPageRouteSpec<Node>;\n\nexport const buildTabsItems = <Node>(input: {\n pages: readonly DetailPage<Node>[];\n id: string;\n tApp: TFunction;\n detailPageHref: (id: string, pageId: string) => string;\n}): readonly BackofficeTabItem[] => {\n return input.pages.map((page) => {\n return {\n id: page.id,\n label: page.label(input.tApp),\n to: input.detailPageHref(input.id, page.id),\n };\n });\n};\n","/* eslint-disable no-ternary */\nimport { type JSX, type ReactNode, useContext, useMemo, useState } from 'react';\nimport type { TFunction } from 'i18next';\nimport { useTranslation } from 'react-i18next';\nimport {\n commitMutation,\n type PreloadedQuery,\n useFragment,\n usePreloadedQuery,\n} from 'react-relay';\nimport type { OperationType } from 'relay-runtime';\nimport {\n type MutationPayloadBase,\n resolveMutationOutcome,\n} from '../relay/mutationResult.js';\nimport { setWhereValue } from '@plumile/backoffice-core/filters/where.js';\nimport {\n buildBackofficeFallbackListHref,\n buildBackofficeListHref,\n buildBackofficeListLink,\n} from '@plumile/backoffice-core/state/buildListHref.js';\n\nimport { BACKOFFICE_DATE_TIME_OPTIONS } from '@plumile/backoffice-core/constants.js';\nimport type {\n BackofficeBadgeTone,\n BackofficeDetailBlockSpec,\n BackofficeDetailFieldSpec,\n BackofficeDetailHeaderConfig,\n BackofficeDetailHeaderMetaSpec,\n BackofficeDetailHeaderStatusSpec,\n BackofficeFlagVariant,\n BackofficeEntityActionSpec,\n BackofficeEntityFormMutationActionSpec,\n BackofficeEntityMutationActionSpec,\n BackofficeEntityRouteActionSpec,\n BackofficeInlineValueSpec,\n BackofficeResolvedDetailLayoutFacetConfigBase,\n BackofficeResolvedDetailPageFacetConfig,\n BackofficeResolvedDetailPageFacetConfigBase,\n BackofficeValueLabel,\n I18nLabel,\n} from '@plumile/backoffice-core/types.js';\nimport {\n BackofficeKeyValueList,\n BackofficePageHeader,\n BackofficeRelationsMenu,\n BackofficeTabs,\n type BackofficeRelationsMenuItem,\n type BackofficeTabItem,\n Button,\n ChatCheckSvg,\n DataTable,\n DetailPageTemplate,\n type EntityHeaderItem,\n FormattedDate,\n HighlightCode,\n KeyOffSvg,\n KeySvg,\n LazyBackofficeJsonViewer,\n LinkButton,\n LockOpenSvg,\n LockSvg,\n RobotCheckSvg,\n RobotXSvg,\n RocketOffSvg,\n RocketSvg,\n SettingsCheckSvg,\n SettingsXSvg,\n ShieldLockSvg,\n ShieldOffSvg,\n Tag,\n useToast,\n XBadgeSvg,\n} from '@plumile/ui';\nimport { HttpRedirect, Link, RoutingContext } from '@plumile/router';\n\nimport { buildDataTableColumns } from '../components/backoffice/columns/buildDataTableColumns.js';\nimport { BackofficeEntityDetailScaffold } from '../components/backoffice/scaffolds/BackofficeEntityDetailScaffold.js';\nimport { BackofficeDetailBadgeRow } from '../components/backoffice/detail/BackofficeDetailBadgeRow.js';\nimport { BackofficeDetailFlagTag } from '../components/backoffice/detail/BackofficeDetailFlagTag.js';\nimport { BackofficeDetailTaggedValue } from '../components/backoffice/detail/BackofficeDetailTaggedValue.js';\nimport { BackofficeDetailPayload } from '../components/backoffice/detail/BackofficeDetailPayload.js';\nimport { BackofficeDetailErrorList } from '../components/backoffice/detail/BackofficeDetailErrorList.js';\nimport { BackofficeDetailRelationListBlock } from '../components/backoffice/detail/BackofficeDetailRelationListBlock.js';\nimport { BackofficeDetailSection } from '../components/backoffice/detail/BackofficeDetailSection.js';\nimport { LazyBackofficeEntityActionFormDialog } from '../components/backoffice/actions/LazyBackofficeEntityActionFormDialog.js';\nimport {\n resolveToastSpec,\n resolveToastViewActions,\n} from '../components/backoffice/actions/toastViewAction.js';\nimport * as pageStyles from './backofficeEntityDetailPage.css.js';\nimport type { BackofficeDetailFieldProps } from '../components/backoffice/detail/BackofficeDetailField.js';\nimport { useBackofficeFormats } from '../i18n/useBackofficeFormats.js';\nimport { useBackofficeReactTranslation } from '../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeConfig } from '../provider/BackofficeConfigContext.js';\nimport { useRelayEnvironment } from '../relay/useRelayEnvironment.js';\nimport { useBackofficeEntityDetailLayoutContext } from './detail/BackofficeEntityDetailLayoutContext.js';\nimport { buildTabsItems } from './detail/buildTabsItems.js';\nimport { resolveVisibleDetailPages } from './detail/pageResolution.js';\nimport { BackofficeRightPageLayout } from '../components/backoffice/layout/breadcrumb/BackofficeRightPageLayout.js';\nimport { buildEntityDetailBreadcrumb } from '../components/backoffice/layout/breadcrumb/buildBreadcrumbs.js';\n\nexport type BackofficeEntityDetailPageProps = {\n config: BackofficeResolvedDetailLayoutFacetConfigBase;\n prepared: {\n id: string;\n detailId?: string;\n pageConfig: BackofficeResolvedDetailPageFacetConfigBase;\n pageQuery: PreloadedQuery<OperationType>;\n pageId: string;\n pagePath: string;\n };\n};\n\nconst resolveLabel = (label: I18nLabel, tApp: TFunction): string => {\n return label(tApp);\n};\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n return typeof value === 'object' && value != null && !Array.isArray(value);\n};\n\nconst assertNever = (value: never): never => {\n throw new Error(`Unexpected value: ${String(value)}`);\n};\n\ntype FlagTagSpec = {\n tone: 'neutral' | 'info' | 'success' | 'warning' | 'danger';\n label: string;\n icon?: JSX.Element;\n};\n\nconst resolveFlagTag = (\n variant: BackofficeFlagVariant,\n value: boolean,\n t: TFunction,\n): FlagTagSpec => {\n const iconSize = 14;\n\n switch (variant) {\n case 'yesNo': {\n if (value) {\n return {\n tone: 'success',\n label: t('common.boolean.yes'),\n };\n }\n return {\n tone: 'neutral',\n label: t('common.boolean.no'),\n };\n }\n case 'capability': {\n if (value) {\n return {\n tone: 'success',\n label: t('flags.capability.allowed'),\n icon: (\n <ShieldLockSvg\n width={iconSize}\n height={iconSize}\n aria-hidden=\"true\"\n />\n ),\n };\n }\n return {\n tone: 'neutral',\n label: t('flags.capability.denied'),\n icon: (\n <ShieldOffSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n ),\n };\n }\n case 'enabled': {\n if (value) {\n return {\n tone: 'success',\n label: t('flags.enabled.enabled'),\n icon: (\n <SettingsCheckSvg\n width={iconSize}\n height={iconSize}\n aria-hidden=\"true\"\n />\n ),\n };\n }\n return {\n tone: 'neutral',\n label: t('flags.enabled.disabled'),\n icon: (\n <SettingsXSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n ),\n };\n }\n case 'failure': {\n if (value) {\n return {\n tone: 'danger',\n label: t('flags.failure.failed'),\n icon: (\n <XBadgeSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n ),\n };\n }\n return {\n tone: 'success',\n label: t('flags.failure.ok'),\n icon: (\n <ChatCheckSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n ),\n };\n }\n case 'encrypted': {\n if (value) {\n return {\n tone: 'info',\n label: t('flags.encrypted.encrypted'),\n icon: (\n <KeySvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n ),\n };\n }\n return {\n tone: 'neutral',\n label: t('flags.encrypted.notEncrypted'),\n icon: (\n <KeyOffSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n ),\n };\n }\n case 'locked': {\n if (value) {\n return {\n tone: 'warning',\n label: t('flags.locked.locked'),\n icon: (\n <LockSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n ),\n };\n }\n return {\n tone: 'success',\n label: t('flags.locked.unlocked'),\n icon: (\n <LockOpenSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n ),\n };\n }\n case 'default': {\n if (value) {\n return {\n tone: 'info',\n label: t('flags.default.default'),\n };\n }\n return {\n tone: 'neutral',\n label: t('flags.default.notDefault'),\n };\n }\n case 'agentManaged': {\n if (value) {\n return {\n tone: 'info',\n label: t('flags.agentManaged.agentManaged'),\n icon: (\n <RobotCheckSvg\n width={iconSize}\n height={iconSize}\n aria-hidden=\"true\"\n />\n ),\n };\n }\n return {\n tone: 'neutral',\n label: t('flags.agentManaged.userManaged'),\n icon: (\n <RobotXSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n ),\n };\n }\n case 'deployedProduction': {\n if (value) {\n return {\n tone: 'success',\n label: t('flags.deployedProduction.deployed'),\n icon: (\n <RocketSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n ),\n };\n }\n return {\n tone: 'neutral',\n label: t('flags.deployedProduction.notDeployed'),\n icon: (\n <RocketOffSvg width={iconSize} height={iconSize} aria-hidden=\"true\" />\n ),\n };\n }\n case 'forced': {\n if (value) {\n return {\n tone: 'warning',\n label: t('flags.forced.forced'),\n };\n }\n return {\n tone: 'neutral',\n label: t('flags.forced.normal'),\n };\n }\n default:\n return assertNever(variant);\n }\n};\n\nconst extractMutationPayload = (\n response: unknown,\n): MutationPayloadBase | null => {\n if (!isPlainObject(response)) {\n return null;\n }\n\n for (const value of Object.values(response)) {\n if (isPlainObject(value) && ('status' in value || 'result' in value)) {\n return value as MutationPayloadBase;\n }\n }\n\n return null;\n};\n\nconst isRouteAction = <Node,>(\n action: BackofficeEntityActionSpec<Node>,\n): action is BackofficeEntityRouteActionSpec<Node> => {\n return action.kind === 'route';\n};\n\nconst isMutationAction = <Node,>(\n action: BackofficeEntityActionSpec<Node>,\n): action is BackofficeEntityMutationActionSpec<Node> => {\n return action.kind === 'mutation';\n};\n\nconst isFormMutationAction = <Node,>(\n action: BackofficeEntityActionSpec<Node>,\n): action is BackofficeEntityFormMutationActionSpec<Node> => {\n return action.kind === 'formMutation';\n};\n\nconst resolveValueLabel = (\n value: BackofficeValueLabel | null | undefined,\n tApp: TFunction,\n): string | number | null => {\n if (typeof value === 'function') {\n return value(tApp);\n }\n if (value == null) {\n return null;\n }\n return value;\n};\n\nconst resolveRelationValue = (value: string | null): string | null => {\n if (value == null) {\n return null;\n }\n const trimmed = value.trim();\n if (trimmed === '') {\n return null;\n }\n return trimmed;\n};\n\nconst isEmptyText = (value: string | number | null | undefined): boolean => {\n if (value == null) {\n return true;\n }\n if (typeof value === 'string') {\n return value.trim() === '';\n }\n return false;\n};\n\nconst resolveBadgeTone = <Node,>(\n tone: BackofficeBadgeTone | ((node: Node) => BackofficeBadgeTone) | undefined,\n node: Node,\n): BackofficeBadgeTone | undefined => {\n if (typeof tone === 'function') {\n return tone(node);\n }\n return tone;\n};\n\nconst resolveInlineValue = (\n value: BackofficeInlineValueSpec,\n options: {\n tApp: TFunction;\n t: TFunction;\n resolveEntityHref?: (entityId: string, refId: string) => string | null;\n },\n): ReactNode => {\n const { tApp, t, resolveEntityHref } = options;\n const fallback = t('common.notAvailable');\n\n if (value.type === 'text') {\n const resolved = resolveValueLabel(value.value, tApp);\n return isEmptyText(resolved) ? fallback : resolved;\n }\n\n if (value.type === 'entityRef') {\n const { id } = value;\n if (id == null || id.trim() === '') {\n return fallback;\n }\n const resolvedLabel = resolveValueLabel(value.label, tApp);\n const label =\n resolvedLabel != null && String(resolvedLabel).trim() !== ''\n ? resolvedLabel\n : null;\n if (label == null) {\n return fallback;\n }\n const href = resolveEntityHref?.(value.entity, id) ?? null;\n if (href != null) {\n return <Link to={href}>{label}</Link>;\n }\n return label;\n }\n\n const { href } = value;\n if (href == null || href.trim() === '') {\n return fallback;\n }\n const label = resolveValueLabel(value.label, tApp);\n if (isEmptyText(label)) {\n return fallback;\n }\n return <Link to={href}>{label}</Link>;\n};\n\nconst buildFieldItems = <Node,>(\n fields: readonly BackofficeDetailFieldSpec<Node>[],\n node: Node,\n options: {\n tApp: TFunction;\n t: TFunction;\n resolveEntityHref?: (entityId: string, refId: string) => string | null;\n formatNumber: (value: number | null | undefined) => string;\n formatCurrency: (value: number | null | undefined) => string;\n formatPercent: (value: number | null | undefined) => string;\n relationEntityListRoutes: Record<string, string>;\n resolveRelationItem: (args: {\n id: string;\n label: string;\n count: number | null;\n entityId: string;\n filterId?: string;\n listRoute: string;\n path?: readonly string[];\n value: string;\n where: Record<string, unknown>;\n whereKey: string;\n }) => BackofficeRelationsMenuItem;\n },\n): {\n items: BackofficeDetailFieldProps[];\n relationItems: BackofficeRelationsMenuItem[];\n customNodes: ReactNode[];\n} => {\n const {\n tApp,\n t,\n resolveEntityHref,\n formatNumber,\n formatCurrency,\n formatPercent,\n relationEntityListRoutes,\n resolveRelationItem,\n } = options;\n const items: BackofficeDetailFieldProps[] = [];\n const relationItems: BackofficeRelationsMenuItem[] = [];\n const customNodes: ReactNode[] = [];\n const fallback = t('common.notAvailable');\n\n fields.forEach((field, index) => {\n const id = `${field.type}-${index}`;\n\n switch (field.type) {\n case 'text': {\n const value = resolveValueLabel(field.value(node), tApp);\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value,\n copyValue: field.copyValue?.(node) ?? undefined,\n fullWidth: field.fullWidth,\n });\n break;\n }\n case 'badge': {\n const value = resolveValueLabel(field.value(node), tApp);\n const label = value != null ? String(value) : '';\n const tone = resolveBadgeTone(field.tone, node);\n const badgeNode =\n label.trim() !== '' ? <Tag tone={tone}>{label}</Tag> : null;\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value: badgeNode,\n });\n break;\n }\n case 'badgeRow': {\n const badgeItems = field.items(node).map((item) => {\n const resolvedLabel = resolveValueLabel(item.label, tApp);\n const label = resolvedLabel == null ? '' : String(resolvedLabel);\n return { ...item, label };\n });\n const value =\n badgeItems.length > 0 ? (\n <BackofficeDetailBadgeRow items={badgeItems} />\n ) : null;\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value,\n fullWidth: field.fullWidth,\n });\n break;\n }\n case 'dateTime': {\n const value = field.value(node);\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value: (\n <FormattedDate\n value={value}\n options={BACKOFFICE_DATE_TIME_OPTIONS}\n fallback={t('common.notAvailable')}\n />\n ),\n });\n break;\n }\n case 'number': {\n const value = field.value(node);\n let formatted: string | null = null;\n if (value != null) {\n if (field.format === 'currency') {\n formatted = formatCurrency(value);\n } else if (field.format === 'percent') {\n formatted = formatPercent(value);\n } else {\n formatted = formatNumber(value);\n }\n }\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value: formatted,\n });\n break;\n }\n case 'flag': {\n const value = field.value(node);\n let resolved: ReactNode | null = null;\n if (value != null) {\n const tag = resolveFlagTag(field.variant, value, t);\n resolved = (\n <BackofficeDetailFlagTag\n tone={tag.tone}\n icon={tag.icon}\n label={tag.label}\n />\n );\n }\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value: resolved,\n });\n break;\n }\n case 'entityRef': {\n const idValue = field.id(node);\n let value: ReactNode | null = null;\n if (idValue != null && idValue.trim() !== '') {\n const labelValue = field.value?.(node);\n const label =\n labelValue != null && labelValue.trim() !== '' ? labelValue : null;\n const href = resolveEntityHref?.(field.entity, idValue) ?? null;\n if (label != null) {\n if (href != null) {\n value = <Link to={href}>{label}</Link>;\n } else {\n value = label;\n }\n }\n }\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value: value ?? fallback,\n });\n break;\n }\n case 'link': {\n const href = field.href(node);\n const labelValue = field.value(node);\n const value =\n href != null && href.trim() !== '' && !isEmptyText(labelValue) ? (\n <Link to={href}>{labelValue}</Link>\n ) : null;\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value,\n });\n break;\n }\n case 'taggedValue': {\n const tag = field.tag(node);\n const inlineValue = field.value(node);\n const valueNode = resolveInlineValue(inlineValue, {\n tApp,\n t,\n resolveEntityHref,\n });\n const resolvedTag =\n tag == null\n ? null\n : {\n ...tag,\n label: (() => {\n const labelValue = resolveValueLabel(tag.label, tApp);\n return labelValue == null ? '' : String(labelValue);\n })(),\n };\n const value =\n resolvedTag != null || valueNode != null ? (\n <BackofficeDetailTaggedValue tag={resolvedTag} value={valueNode} />\n ) : null;\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value,\n fullWidth: field.fullWidth,\n });\n break;\n }\n case 'relation': {\n const value = resolveRelationValue(field.value(node));\n if (value == null) {\n break;\n }\n const listRoute = relationEntityListRoutes[field.entity];\n if (listRoute == null) {\n break;\n }\n const labelBase = resolveLabel(field.label, tApp);\n const count = field.count?.(node) ?? null;\n const where = setWhereValue<Record<string, unknown>>(\n null,\n field.whereKey as never,\n value,\n field.path,\n );\n if (where == null) {\n break;\n }\n relationItems.push(\n resolveRelationItem({\n id,\n label: labelBase,\n count,\n entityId: field.entity,\n filterId: field.filterId,\n listRoute,\n path: field.path,\n value,\n where,\n whereKey: field.whereKey,\n }),\n );\n break;\n }\n case 'custom': {\n const custom = field.render(node) as ReactNode;\n if (custom == null) {\n break;\n }\n if (field.label != null) {\n items.push({\n id,\n label: resolveLabel(field.label, tApp),\n size: field.size,\n value: custom,\n fullWidth: field.fullWidth,\n });\n break;\n }\n customNodes.push(<div key={id}>{custom}</div>);\n break;\n }\n default:\n break;\n }\n });\n\n return { items, relationItems, customNodes };\n};\n\nconst resolveHeaderMeta = <Node,>(\n meta: BackofficeDetailHeaderMetaSpec<Node>,\n node: Node,\n options: {\n tApp: TFunction;\n t: TFunction;\n resolveEntityHref?: (entityId: string, refId: string) => string | null;\n },\n): ReactNode => {\n const { tApp, t, resolveEntityHref } = options;\n const fallback = t('common.notAvailable');\n\n if (meta.type === 'dateTime') {\n const value = meta.value(node);\n return (\n <FormattedDate\n value={value}\n options={BACKOFFICE_DATE_TIME_OPTIONS}\n fallback={fallback}\n />\n );\n }\n\n if (meta.type === 'entityRef') {\n const idValue = meta.id(node);\n if (idValue == null || idValue.trim() === '') {\n return fallback;\n }\n const labelValue = resolveValueLabel(meta.value?.(node), tApp);\n const label =\n labelValue != null && String(labelValue).trim() !== ''\n ? labelValue\n : null;\n if (label == null) {\n return fallback;\n }\n const href = resolveEntityHref?.(meta.entity, idValue) ?? null;\n if (href != null) {\n return <Link to={href}>{label}</Link>;\n }\n return label;\n }\n\n if (meta.type === 'link') {\n const href = meta.href(node);\n const labelValue = resolveValueLabel(meta.value(node), tApp);\n if (href == null || href.trim() === '' || isEmptyText(labelValue)) {\n return fallback;\n }\n return <Link to={href}>{labelValue}</Link>;\n }\n\n const value = resolveValueLabel(meta.value(node), tApp);\n return isEmptyText(value) ? fallback : value;\n};\n\nconst resolveHeaderStatus = <Node,>(\n status: BackofficeDetailHeaderStatusSpec<Node>,\n node: Node,\n tApp: TFunction,\n): ReactNode | undefined => {\n if (status.type === 'badgeRow') {\n const items = status.items(node).map((item) => {\n const resolvedLabel = resolveValueLabel(item.label, tApp);\n const label = resolvedLabel == null ? '' : String(resolvedLabel);\n return { ...item, label };\n });\n if (items.length === 0) {\n return undefined;\n }\n return <BackofficeDetailBadgeRow items={items} />;\n }\n\n const value = resolveValueLabel(status.value(node), tApp);\n const label = value == null ? '' : String(value);\n if (label.trim() === '') {\n return undefined;\n }\n const tone = resolveBadgeTone(status.tone, node);\n return <Tag tone={tone}>{label}</Tag>;\n};\n\nconst resolveHeaderItems = <Node,>(\n header: BackofficeDetailHeaderConfig<Node>,\n node: Node,\n options: {\n tApp: TFunction;\n t: TFunction;\n resolveEntityHref?: (entityId: string, refId: string) => string | null;\n },\n): {\n title: string;\n subtitle?: ReactNode;\n badges?: ReactNode;\n status?: ReactNode;\n items?: readonly EntityHeaderItem[];\n} => {\n const { tApp, t, resolveEntityHref } = options;\n const resolvedTitle =\n header.titleValue?.(node, tApp) ?? resolveLabel(header.title, tApp);\n const title =\n resolvedTitle.trim() === ''\n ? resolveLabel(header.title, tApp)\n : resolvedTitle;\n\n let subtitleNode: ReactNode | undefined;\n if (header.subtitleItems != null && header.subtitleItems.length > 0) {\n const separator = header.subtitleSeparator ?? ' / ';\n const parts: ReactNode[] = [];\n const { subtitleItems } = header;\n subtitleItems.forEach((item, index) => {\n const valueSpec = item.value(node);\n parts.push(\n <span key={item.id}>\n {resolveInlineValue(valueSpec, {\n tApp,\n t,\n resolveEntityHref,\n })}\n </span>,\n );\n if (index < subtitleItems.length - 1) {\n parts.push(<span key={`${item.id}-sep`}>{separator}</span>);\n }\n });\n subtitleNode = <span>{parts}</span>;\n } else {\n const subtitleValue =\n header.subtitleValue?.(node, tApp) ??\n (header.subtitle != null ? resolveLabel(header.subtitle, tApp) : null);\n subtitleNode =\n subtitleValue != null && subtitleValue.trim() !== ''\n ? subtitleValue\n : undefined;\n }\n\n const badgeNodes: ReactNode[] = [];\n if (header.badges != null) {\n header.badges.forEach((badge, index) => {\n const label = resolveLabel(badge.label, tApp);\n const resolvedValue = resolveValueLabel(badge.value(node), tApp);\n const value = resolvedValue == null ? '' : String(resolvedValue);\n if (value.trim() === '') {\n return;\n }\n const tone = resolveBadgeTone(badge.tone, node);\n badgeNodes.push(\n <Tag key={`${label}-${index}`} tone={tone}>\n {`${label}: ${value}`}\n </Tag>,\n );\n });\n }\n\n let statusNode: ReactNode | undefined;\n if (header.status != null) {\n statusNode = resolveHeaderStatus(header.status, node, tApp);\n }\n\n const items: EntityHeaderItem[] | undefined = header.meta?.map(\n (meta, index) => {\n const label = resolveLabel(meta.label, tApp);\n const valueNode = resolveHeaderMeta(meta, node, {\n tApp,\n t,\n resolveEntityHref,\n });\n return {\n id: `${label}-${index}`,\n label,\n value: valueNode,\n };\n },\n );\n\n return {\n title,\n subtitle: subtitleNode,\n badges: badgeNodes.length > 0 ? <>{badgeNodes}</> : undefined,\n status: statusNode,\n items,\n };\n};\n\nconst renderBlocks = <Node,>(\n blocks: readonly BackofficeDetailBlockSpec<Node>[] | undefined,\n node: Node,\n options: {\n tApp: TFunction;\n t: TFunction;\n resolveEntityHref: (entityId: string, refId: string) => string | null;\n keyPrefix?: string;\n },\n): ReactNode[] => {\n const { tApp, t, resolveEntityHref } = options;\n if (blocks == null || blocks.length === 0) {\n return [];\n }\n\n return blocks.map((block, index) => {\n const key =\n options.keyPrefix != null\n ? `${options.keyPrefix}-${block.kind}-${index}`\n : `${block.kind}-${index}`;\n\n if (block.kind === 'custom') {\n const custom = block.render(node) as ReactNode;\n if (custom == null) {\n return null;\n }\n if (block.label != null) {\n const customTitle = resolveLabel(block.label, tApp);\n return (\n <BackofficeDetailSection key={key} title={customTitle}>\n {custom}\n </BackofficeDetailSection>\n );\n }\n return <div key={key}>{custom}</div>;\n }\n\n const title = resolveLabel(block.label, tApp);\n const description =\n block.description != null\n ? resolveLabel(block.description, tApp)\n : undefined;\n\n if (block.kind === 'relationList') {\n const value = block.value(node);\n return (\n <BackofficeDetailRelationListBlock\n key={key}\n title={title}\n target={block.target}\n whereKey={block.whereKey}\n value={value}\n path={block.path}\n />\n );\n }\n\n if (block.kind === 'table') {\n const rows = block.rows(node);\n const columns = buildDataTableColumns(block.columns, {\n tApp,\n t,\n resolveEntityHref,\n });\n return (\n <BackofficeDetailSection\n key={key}\n title={title}\n description={description}\n >\n <DataTable\n columns={columns}\n rows={rows}\n getRowId={(row, rowIndex) => {\n if (row != null && typeof row === 'object') {\n const record = row as Record<string, unknown>;\n const maybeId = record.id;\n if (typeof maybeId === 'string' && maybeId.trim() !== '') {\n return maybeId;\n }\n }\n return String(rowIndex);\n }}\n />\n </BackofficeDetailSection>\n );\n }\n\n if (block.kind === 'json') {\n const value = block.value(node);\n return (\n <BackofficeDetailSection\n key={key}\n title={title}\n description={description}\n >\n <LazyBackofficeJsonViewer value={value} title={title} />\n </BackofficeDetailSection>\n );\n }\n\n if (block.kind === 'code') {\n const value = block.value(node);\n return (\n <BackofficeDetailSection\n key={key}\n title={title}\n description={description}\n >\n <HighlightCode\n badgeLabel={t('tools.output')}\n copyCode={value}\n fallbackCodeText={value}\n />\n </BackofficeDetailSection>\n );\n }\n\n if (block.kind === 'payload') {\n const value = block.value(node);\n return (\n <BackofficeDetailPayload\n key={key}\n title={title}\n description={description}\n content={value}\n format={block.format}\n />\n );\n }\n\n if (block.kind === 'errorList') {\n const items = block.errors(node);\n return (\n <BackofficeDetailErrorList\n key={key}\n title={title}\n description={description}\n items={items}\n />\n );\n }\n\n const items = block.items.map((item, itemIndex) => {\n const label = resolveLabel(item.label, tApp);\n const resolvedValue = resolveValueLabel(item.value(node), tApp);\n return {\n id: `${label}-${itemIndex}`,\n label,\n value: resolvedValue ?? t('common.notAvailable'),\n };\n });\n\n return (\n <BackofficeDetailSection\n key={key}\n title={title}\n description={description}\n >\n <BackofficeKeyValueList items={items} />\n </BackofficeDetailSection>\n );\n });\n};\n\nconst BackofficeEntityDetailPageContent = ({\n config,\n prepared,\n}: {\n config: BackofficeResolvedDetailPageFacetConfig;\n prepared: {\n pageQuery: PreloadedQuery<OperationType>;\n id: string;\n detailId?: string;\n pageId: string;\n pagePath: string;\n };\n}): JSX.Element => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const { formatNumber, formatCurrency, formatPercent } =\n useBackofficeFormats();\n const { entities, entityRegistry } = useBackofficeConfig();\n const { layoutView } = useBackofficeEntityDetailLayoutContext();\n const routing = useContext(RoutingContext);\n const environment = useRelayEnvironment();\n const toast = useToast();\n const [actionState, setActionState] = useState<Record<string, boolean>>({});\n const [activeFormActionId, setActiveFormActionId] = useState<string | null>(\n null,\n );\n const resolvedPages = resolveVisibleDetailPages({\n mainPage: config.pages.mainPage,\n subPages: config.pages.subPages,\n activePagePath: prepared.pagePath,\n node: layoutView as never,\n });\n const activePage = resolvedPages.activePage ?? config.pages.mainPage;\n const pages =\n resolvedPages.pages.length > 0\n ? resolvedPages.pages\n : [config.pages.mainPage];\n\n const setActionLoading = (actionId: string, isLoading: boolean) => {\n setActionState((prev) => {\n if (prev[actionId] === isLoading) {\n return prev;\n }\n return { ...prev, [actionId]: isLoading };\n });\n };\n\n const { page } = config;\n\n const pageQueryData = usePreloadedQuery(page.query, prepared.pageQuery);\n const pageNodeRef = page.resolveNode(pageQueryData as never, {\n id: prepared.id,\n detailId: prepared.detailId,\n });\n if (pageNodeRef == null) {\n throw new HttpRedirect(config.routes.list);\n }\n const resolvedNode = useFragment(page.fragment, pageNodeRef as never);\n const relationEntityListRoutes = useMemo(() => {\n return Object.fromEntries(\n page.content\n .flatMap((block) => {\n if (block.kind !== 'section') {\n return [];\n }\n\n return block.fields.flatMap((field) => {\n if (field.type !== 'relation') {\n return [];\n }\n return [field.entity];\n });\n })\n .flatMap((entityId) => {\n const entityManifest = entities[entityId];\n if (entityManifest?.hasList !== true) {\n return [];\n }\n return [[entityId, entityManifest.routes.list]];\n }),\n ) as Record<string, string>;\n }, [entities, page.content]);\n\n return (\n <BackofficeEntityDetailScaffold\n node={resolvedNode as { __typename: string } | null | undefined}\n render={(node) => {\n const view = page.toView(node);\n const tabsItems = buildTabsItems({\n pages,\n id: prepared.id,\n tApp,\n detailPageHref: config.routes.detailPage,\n });\n const resolveEntityHref = (entityId: string, refId: string) => {\n const entityConfig = entities[entityId];\n if (entityConfig == null) {\n return null;\n }\n return entityConfig.routes.detail(refId);\n };\n const resolveRelationItem = ({\n id,\n label,\n count,\n entityId,\n filterId,\n listRoute,\n path,\n value,\n where,\n whereKey,\n }: {\n id: string;\n label: string;\n count: number | null;\n entityId: string;\n filterId?: string;\n listRoute: string;\n path?: readonly string[];\n value: string;\n where: Record<string, unknown>;\n whereKey: string;\n }): BackofficeRelationsMenuItem => {\n const loadedEntity = entityRegistry.getLoadedListEntity(entityId);\n return {\n id,\n label,\n count,\n href:\n loadedEntity == null\n ? buildBackofficeFallbackListHref(listRoute, where, [\n {\n id:\n filterId ??\n (path == null\n ? whereKey\n : `${whereKey}.${path.join('.')}`),\n value,\n },\n ])\n : buildBackofficeListHref(loadedEntity.config, { where }),\n onClick: async (event) => {\n if (\n routing == null ||\n event.defaultPrevented ||\n event.button !== 0 ||\n event.metaKey ||\n event.altKey ||\n event.ctrlKey ||\n event.shiftKey\n ) {\n return;\n }\n\n event.preventDefault();\n\n const listEntity = await entityRegistry.loadListEntity(entityId);\n const next = buildBackofficeListLink(listEntity.config, {\n where,\n });\n\n routing.history.push({\n pathname: next.pathname,\n search: next.search === '' ? '' : `?${next.search}`,\n hash: '',\n });\n },\n };\n };\n\n const header = resolveHeaderItems(config.header, layoutView, {\n tApp,\n t,\n resolveEntityHref,\n });\n const breadcrumb = buildEntityDetailBreadcrumb({\n config,\n tApp,\n entityId: prepared.id,\n layoutView,\n pageLabel: activePage.label(tApp),\n });\n\n const actions = page.actions ?? [];\n let headerActionButtons: ReactNode[] = [];\n if (actions.length > 0) {\n const visibleActions = actions.filter((action) => {\n if (action.isVisible == null) {\n return true;\n }\n return action.isVisible(view);\n });\n\n if (visibleActions.length > 0) {\n headerActionButtons = visibleActions.map((action) => {\n const label = resolveLabel(action.label, tApp);\n const ariaLabel =\n action.ariaLabel != null\n ? resolveLabel(action.ariaLabel, tApp)\n : label;\n const variant = action.variant ?? 'secondary';\n const size = action.size ?? 'small';\n const isLoading = actionState[action.id] ?? false;\n const isDisabled =\n isLoading || action.isDisabled?.(view) === true;\n\n if (isRouteAction(action)) {\n const href = action.to(view);\n return (\n <LinkButton\n key={action.id}\n to={href}\n variant={variant}\n size={size}\n isDisabled={isDisabled}\n aria-label={ariaLabel}\n >\n {label}\n </LinkButton>\n );\n }\n\n if (isFormMutationAction(action)) {\n return (\n <Button\n key={action.id}\n type=\"button\"\n variant={variant}\n size={size}\n isLoading={false}\n disabled={isDisabled}\n onClick={() => {\n setActiveFormActionId(action.id);\n }}\n aria-label={ariaLabel}\n >\n {label}\n </Button>\n );\n }\n\n if (isMutationAction(action)) {\n const handleClick = () => {\n if (isLoading) {\n return;\n }\n const variables = action.getVariables(view);\n setActionLoading(action.id, true);\n commitMutation(environment, {\n mutation: action.mutation,\n variables,\n updater: (store) => {\n action.updater?.(store, view);\n },\n onCompleted: (response) => {\n setActionLoading(action.id, false);\n const mutationPayload = extractMutationPayload(response);\n if (mutationPayload != null) {\n let defaultErrorMessage = t(\n 'actions.form.errors.invalidPayload',\n );\n if (action.toasts?.error?.message != null) {\n defaultErrorMessage = resolveLabel(\n action.toasts.error.message,\n tApp,\n );\n } else if (action.toasts?.error?.title != null) {\n defaultErrorMessage = resolveLabel(\n action.toasts.error.title,\n tApp,\n );\n }\n\n const outcome = resolveMutationOutcome(\n mutationPayload,\n {\n defaultErrorMessage,\n mapReason: (reason) => {\n const mapped = action.mapErrorReason?.(\n reason,\n view,\n );\n if (mapped == null) {\n return null;\n }\n if (typeof mapped === 'function') {\n return resolveLabel(mapped, tApp);\n }\n return String(mapped);\n },\n },\n );\n if (!outcome.ok) {\n const error = new Error(outcome.message);\n action.onError?.(error, view);\n if (action.toasts?.error != null) {\n const toastSpec = resolveToastSpec(\n action.toasts.error,\n tApp,\n );\n toast.error(toastSpec.title, toastSpec.message);\n }\n return;\n }\n }\n\n action.onCompleted?.(response, view);\n if (action.toasts?.success != null) {\n const toastSpec = resolveToastSpec(\n action.toasts.success,\n tApp,\n );\n const toastActions = resolveToastViewActions({\n toast: action.toasts.success,\n response,\n node: view,\n tApp,\n entities,\n defaultLabel: t('actions.view'),\n navigateTo: (to) => {\n routing?.history.push({ pathname: to });\n },\n });\n toast.push({\n kind: 'info',\n title: toastSpec.title,\n message: toastSpec.message,\n actions: toastActions,\n });\n }\n },\n onError: (error) => {\n setActionLoading(action.id, false);\n action.onError?.(error, view);\n if (action.toasts?.error != null) {\n const toastSpec = resolveToastSpec(\n action.toasts.error,\n tApp,\n );\n toast.error(toastSpec.title, toastSpec.message);\n }\n },\n });\n };\n\n return (\n <Button\n key={action.id}\n type=\"button\"\n variant={variant}\n size={size}\n isLoading={isLoading}\n disabled={isDisabled}\n onClick={handleClick}\n aria-label={ariaLabel}\n >\n {label}\n </Button>\n );\n }\n\n return null;\n });\n }\n }\n\n const activeFormAction = actions.find((action) => {\n return action.id === activeFormActionId;\n });\n\n const { content } = page;\n\n const primaryNodes: ReactNode[] = [];\n const secondaryNodes: ReactNode[] = [];\n const relationMenuItems: BackofficeRelationsMenuItem[] = [];\n\n content.forEach((item, index) => {\n const placement = item.placement ?? 'primary';\n const targetNodes =\n placement === 'secondary' ? secondaryNodes : primaryNodes;\n\n if (item.kind === 'section') {\n const sectionLabel = resolveLabel(item.title, tApp);\n const description =\n item.description != null\n ? resolveLabel(item.description, tApp)\n : undefined;\n const { items, relationItems, customNodes } = buildFieldItems(\n item.fields,\n view,\n {\n tApp,\n t,\n resolveEntityHref,\n formatNumber,\n formatCurrency,\n formatPercent,\n relationEntityListRoutes,\n resolveRelationItem,\n },\n );\n relationItems.forEach((relation) => {\n if (\n !relationMenuItems.some((entry) => {\n return entry.id === relation.id;\n })\n ) {\n relationMenuItems.push(relation);\n }\n });\n\n const hasContent = items.length > 0 || customNodes.length > 0;\n\n if (!hasContent) {\n return;\n }\n\n targetNodes.push(\n <BackofficeDetailSection\n key={`${sectionLabel}-${index}`}\n title={sectionLabel}\n description={description}\n items={items.length > 0 ? items : undefined}\n >\n {customNodes}\n </BackofficeDetailSection>,\n );\n return;\n }\n\n const rendered = renderBlocks([item], view, {\n tApp,\n t,\n resolveEntityHref,\n keyPrefix: String(index),\n });\n const blockNode = rendered[0];\n if (blockNode != null) {\n targetNodes.push(blockNode);\n }\n });\n\n const relationsMenuNode =\n relationMenuItems.length > 0 ? (\n <BackofficeRelationsMenu\n label={t('relations.menu.label')}\n items={relationMenuItems}\n />\n ) : null;\n\n const headerActions =\n headerActionButtons.length > 0 || relationsMenuNode != null ? (\n <div className={pageStyles.headerActions}>\n {headerActionButtons}\n {relationsMenuNode}\n </div>\n ) : undefined;\n\n const headerMetaNode =\n header.status != null || header.badges != null ? (\n <div className={pageStyles.headerMeta}>\n {header.status}\n {header.badges}\n </div>\n ) : undefined;\n\n const headerItemsNode =\n header.items != null && header.items.length > 0 ? (\n <div className={pageStyles.headerMetaList}>\n <BackofficeKeyValueList items={header.items} />\n </div>\n ) : null;\n\n const hasAside = secondaryNodes.length > 0;\n let tabsNode: JSX.Element | null = null;\n if (pages.length > 1) {\n tabsNode = (\n <BackofficeTabs\n items={tabsItems as BackofficeTabItem[]}\n activeId={activePage.id}\n onChange={() => {}}\n />\n );\n }\n const headerNode = (\n <div className={pageStyles.headerBlock}>\n <BackofficePageHeader\n title={header.title}\n subtitle={header.subtitle}\n actions={headerActions}\n meta={headerMetaNode}\n />\n {headerItemsNode}\n </div>\n );\n\n return (\n <BackofficeRightPageLayout breadcrumb={breadcrumb}>\n <DetailPageTemplate\n headerNode={headerNode}\n tabsNode={tabsNode}\n sidePanel={hasAside ? <>{secondaryNodes}</> : undefined}\n sidePanelVariant=\"plain\"\n >\n <>{primaryNodes}</>\n </DetailPageTemplate>\n {activeFormAction != null &&\n isFormMutationAction(activeFormAction) && (\n <LazyBackofficeEntityActionFormDialog\n isOpen\n action={activeFormAction}\n node={view}\n onClose={() => {\n setActiveFormActionId(null);\n }}\n />\n )}\n </BackofficeRightPageLayout>\n );\n }}\n />\n );\n};\n\nexport const BackofficeEntityDetailPage = ({\n config,\n prepared,\n}: BackofficeEntityDetailPageProps): JSX.Element => {\n const { layoutView } = useBackofficeEntityDetailLayoutContext();\n\n const resolvedPages = resolveVisibleDetailPages({\n mainPage: config.pages.mainPage,\n subPages: config.pages.subPages,\n activePagePath: prepared.pagePath,\n node: layoutView as never,\n });\n\n if (!resolvedPages.hasVisiblePages || resolvedPages.activePage == null) {\n throw new HttpRedirect(config.routes.list);\n }\n\n if (resolvedPages.activePage.id !== prepared.pageId) {\n throw new HttpRedirect(\n config.routes.detailPage(prepared.id, resolvedPages.activePage.id),\n );\n }\n\n return (\n <BackofficeEntityDetailPageContent\n config={prepared.pageConfig}\n prepared={prepared}\n />\n );\n};\n\nexport default BackofficeEntityDetailPage;\n"],"mappings":"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"}
@@ -1,12 +1,12 @@
1
- import { n as e } from "./sprinkles.css.ts.vanilla-n-NK_DwW.js";
1
+ import { n as e } from "./BackofficeConfigContext-R0t1owTI.js";
2
2
  import { t } from "./useBackofficeReactTranslation-WfXU8kCf.js";
3
- import "./EntityFilterValue-SC_jkj4O.js";
4
- import "./EntityIdPickerDialog-FMC5Hx_I.js";
3
+ import "./EntityFilterValue-Bn9VGr2M.js";
4
+ import "./EntityIdPickerDialog-D_qAlrU6.js";
5
5
  import { t as n } from "./useBackofficeListUrlState-D4fx5O7u.js";
6
- import { n as r, t as i } from "./BackofficeRightPageLayout-ktdlvTZJ.js";
6
+ import { n as r, t as i } from "./BackofficeRightPageLayout-D7QRE8KZ.js";
7
7
  import "./BackofficeTopbarPortalContext-iD7dm4_h.js";
8
8
  import { r as a } from "./buildBreadcrumbs-CqF9Nh6x.js";
9
- import { i as o, n as s, r as c, t as l } from "./LazyBackofficeEntityActionFormDialog-DOEgoIfT.js";
9
+ import { i as o, n as s, r as c, t as l } from "./LazyBackofficeEntityActionFormDialog-DndjG4kV.js";
10
10
  import { useCallback as u, useEffect as d, useMemo as f, useRef as p, useState as m } from "react";
11
11
  import { useTranslation as ee } from "react-i18next";
12
12
  import { Button as te, EyeSvg as h, LinkButton as g, TableCell as _ } from "@plumile/ui";
@@ -44,7 +44,7 @@ var T = "wy96wu0", E = "wy96wu1", D = "wy96wu2", O = ({ row: e, flags: t, tApp:
44
44
  children: e.node
45
45
  }, e.id))
46
46
  });
47
- }, oe = "c0tad0 vncd899io vncd89co vncd89ao6 vncd89ajx", k = "c0tad1", A = "c0tad2", se = (e) => e.list.kind === "records", ce = "store-or-network", j = (e, t) => e(t), M = 24, N = 6, P = 4, F = 32, I = 8, L = 12, R = 4, z = (e) => e <= 0 ? 0 : P * 2 + M * e + N * Math.max(0, e - 1), B = (e) => e <= 0 ? 0 : R + L * 2 + F * e + I * Math.max(0, e - 1), V = {
47
+ }, oe = "txvbqb9io txvbqbco txvbqbao6 txvbqbajx", k = "c0tad0", A = "c0tad1", se = (e) => e.list.kind === "records", ce = "store-or-network", j = (e, t) => e(t), M = 24, N = 6, P = 4, F = 32, I = 8, L = 12, R = 4, z = (e) => e <= 0 ? 0 : P * 2 + M * e + N * Math.max(0, e - 1), B = (e) => e <= 0 ? 0 : R + L * 2 + F * e + I * Math.max(0, e - 1), V = {
48
48
  xs: "minmax(56px, 76px)",
49
49
  s: "minmax(88px, 120px)",
50
50
  m: "minmax(120px, 168px)",
@@ -382,4 +382,4 @@ var T = "wy96wu0", E = "wy96wu1", D = "wy96wu2", O = ({ row: e, flags: t, tApp:
382
382
  //#endregion
383
383
  export { K as BackofficeEntityListPage, K as default };
384
384
 
385
- //# sourceMappingURL=BackofficeEntityListPage-BxgqdFpL.js.map
385
+ //# sourceMappingURL=BackofficeEntityListPage-CtLI15-L.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BackofficeEntityListPage-CtLI15-L.js","names":[],"sources":["../../src/components/backoffice/list/RowFlagsCell.css.ts","../../src/components/backoffice/list/RowFlagsCell.tsx","../../src/pages/backofficeEntityListPage.css.ts","../../src/pages/BackofficeEntityListPage.tsx"],"sourcesContent":["import { style } from '@vanilla-extract/css';\n\nexport const rowFlagsColumnCell = style({\n justifyContent: 'center',\n padding: '0 4px',\n});\n\nexport const container = style({\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 6,\n width: '100%',\n});\n\nexport const flag = style({\n display: 'grid',\n placeItems: 'center',\n width: 24,\n height: 24,\n});\n","import { useMemo, type JSX, type ReactNode } from 'react';\nimport type { TFunction } from 'i18next';\n\nimport type { BackofficeRowFlagSpec } from '@plumile/backoffice-core/types.js';\n\nimport * as styles from './RowFlagsCell.css.js';\n\nexport type RowFlagsCellProps<Row> = {\n row: Row;\n flags: readonly BackofficeRowFlagSpec<Row>[];\n tApp: TFunction;\n};\n\n/**\n * Renders row-level flags (icons) in a dedicated compact column.\n */\nexport const RowFlagsCell = <Row,>({\n row,\n flags,\n tApp,\n}: RowFlagsCellProps<Row>): JSX.Element => {\n const resolved = useMemo(() => {\n const out: { id: string; node: ReactNode; label: string }[] = [];\n for (const flag of flags) {\n const node = flag.render(row) as ReactNode;\n if (node != null && node !== '' && node !== false) {\n out.push({ id: flag.id, node, label: flag.label(row)(tApp) });\n }\n }\n return out;\n }, [flags, row, tApp]);\n\n const ariaLabel = resolved\n .map((entry) => {\n return entry.label.trim();\n })\n .filter((label) => {\n return label !== '';\n })\n .join(', ');\n\n let ariaLabelProp: string | undefined;\n if (ariaLabel !== '') {\n ariaLabelProp = ariaLabel;\n }\n\n return (\n <div className={styles.container} aria-label={ariaLabelProp}>\n {resolved.map((entry) => {\n return (\n <span\n key={entry.id}\n className={styles.flag}\n title={entry.label}\n role=\"img\"\n aria-label={entry.label}\n >\n {entry.node}\n </span>\n );\n })}\n </div>\n );\n};\n","import { style } from '@vanilla-extract/css';\nimport { sprinkles } from '@plumile/ui';\n\nexport const headerActions = sprinkles({\n display: 'flex',\n alignItems: 'center',\n gap: 2,\n flexWrap: 'wrap',\n});\n\nexport const actionsColumnCell = style({\n justifyContent: 'flex-end',\n});\n\nexport const actionTrigger = style({\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '2rem',\n height: '2rem',\n flexShrink: 0,\n});\n","/* eslint-disable react-hooks/rules-of-hooks */\nimport {\n type ComponentProps,\n type JSX,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport type { TFunction } from 'i18next';\nimport { useTranslation } from 'react-i18next';\nimport {\n useFragment,\n usePaginationFragment,\n usePreloadedQuery,\n useRelayEnvironment,\n} from 'react-relay';\nimport { fetchQuery } from 'relay-runtime';\nimport {\n BACKOFFICE_LIST_DEFAULTS,\n BACKOFFICE_LIST_REFETCH_POLICY,\n} from '@plumile/backoffice-core/constants.js';\nimport { stableListVariablesKey } from '@plumile/backoffice-core/state/stableKey.js';\nimport type {\n BackofficeEntityManifestItem,\n BackofficeEntityFormMutationActionSpec,\n BackofficeEntityRouteActionSpec,\n BackofficeListActionSpec,\n BackofficePreparedListRoute,\n BackofficeRecordListConfig,\n BackofficeResolvedListFacetConfig,\n BackofficeRowFlagSpec,\n I18nLabel,\n} from '@plumile/backoffice-core/types.js';\nimport {\n Button,\n LinkButton,\n type DataTableColumn,\n EyeSvg,\n type GetRowId,\n TableCell,\n} from '@plumile/ui';\nimport { BackofficeEntityListScaffold } from '../components/backoffice/scaffolds/BackofficeEntityListScaffold.js';\nimport { LazyBackofficeEntityActionFormDialog } from '../components/backoffice/actions/LazyBackofficeEntityActionFormDialog.js';\nimport {\n buildDataTableColumns,\n type BackofficeSizedDataTableColumn,\n} from '../components/backoffice/columns/buildDataTableColumns.js';\nimport { RowFlagsCell } from '../components/backoffice/list/RowFlagsCell.js';\nimport { useBackofficeListUrlState } from '../hooks/useBackofficeListUrlState.js';\nimport { useBackofficeLoadMore } from '../hooks/useBackofficeLoadMore.js';\nimport { useBackofficeListRefetch } from '../hooks/useBackofficeListRefetch.js';\nimport { useBackofficeReactTranslation } from '../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeConfig } from '../provider/BackofficeConfigContext.js';\nimport * as pageStyles from './backofficeEntityListPage.css.js';\nimport { rowFlagsColumnCell } from '../components/backoffice/list/RowFlagsCell.css.js';\nimport { BackofficeRightPageLayout } from '../components/backoffice/layout/breadcrumb/BackofficeRightPageLayout.js';\nimport { buildEntityListBreadcrumb } from '../components/backoffice/layout/breadcrumb/buildBreadcrumbs.js';\n\nexport type BackofficeEntityListPageProps = {\n entityManifest: BackofficeEntityManifestItem;\n config: BackofficeResolvedListFacetConfig;\n prepared: BackofficePreparedListRoute;\n};\n\ntype RecordListConfig = BackofficeResolvedListFacetConfig & {\n list: BackofficeRecordListConfig<\n Record<string, unknown>,\n string,\n unknown,\n unknown,\n unknown,\n unknown,\n Record<string, unknown>\n >;\n};\n\nconst isRecordListConfig = (\n config: BackofficeResolvedListFacetConfig,\n): config is RecordListConfig => {\n return config.list.kind === 'records';\n};\n\ntype RecordFetchMode = 'append' | 'reset';\ntype ButtonVariant = ComponentProps<typeof Button>['variant'];\n\ntype RecordFetchInput = {\n where: Record<string, unknown> | null;\n sort: string | null;\n count: number;\n cursor: string | null;\n mode: RecordFetchMode;\n};\n\nconst RECORD_FETCH_POLICY = 'store-or-network' as const;\n\nconst resolveLabel = (label: I18nLabel, tApp: TFunction): string => {\n return label(tApp);\n};\n\nconst ROW_FLAGS_SLOT_PX = 24;\nconst ROW_FLAGS_GAP_PX = 6;\nconst ROW_FLAGS_PADDING_X_PX = 4;\n\n// Match the actual icon button footprint (32px) plus dense table cell padding.\nconst ACTIONS_SLOT_PX = 32;\nconst ACTIONS_GAP_PX = 8;\nconst ACTIONS_PADDING_X_PX = 12;\nconst ACTIONS_SAFETY_PX = 4;\n\nconst computeRowFlagsColumnWidthPx = (flagCount: number): number => {\n if (flagCount <= 0) {\n return 0;\n }\n return (\n ROW_FLAGS_PADDING_X_PX * 2 +\n ROW_FLAGS_SLOT_PX * flagCount +\n ROW_FLAGS_GAP_PX * Math.max(0, flagCount - 1)\n );\n};\n\nconst computeActionsColumnWidthPx = (actionCount: number): number => {\n if (actionCount <= 0) {\n return 0;\n }\n return (\n ACTIONS_SAFETY_PX +\n ACTIONS_PADDING_X_PX * 2 +\n ACTIONS_SLOT_PX * actionCount +\n ACTIONS_GAP_PX * Math.max(0, actionCount - 1)\n );\n};\n\nconst listColumnTrackBySize: Record<\n BackofficeSizedDataTableColumn<unknown>['size'],\n string\n> = {\n xs: 'minmax(56px, 76px)',\n s: 'minmax(88px, 120px)',\n m: 'minmax(120px, 168px)',\n l: 'minmax(160px, 220px)',\n xl: 'minmax(220px, 300px)',\n // \"fluid\" columns share the available remainder equally.\n fluid: 'minmax(0, 1fr)',\n};\n\nconst resolveTrackBySize = (\n column: DataTableColumn<unknown>,\n fallback: string,\n): string => {\n if ('size' in column && typeof column.size === 'string') {\n return listColumnTrackBySize[\n column.size as BackofficeSizedDataTableColumn<unknown>['size']\n ];\n }\n return fallback;\n};\n\nconst applyListEdgeColumns = <Row,>(\n inputColumns: readonly DataTableColumn<Row>[],\n rowFlags: readonly BackofficeRowFlagSpec<Row>[] | undefined,\n actionCount: number,\n tApp: TFunction,\n): {\n columns: readonly DataTableColumn<Row>[];\n gridTemplateColumns?: string;\n} => {\n const hasFlags = rowFlags != null && rowFlags.length > 0;\n\n let columns = inputColumns;\n if (hasFlags) {\n const flagsColumn: DataTableColumn<Row> = {\n id: '__rowFlags',\n header: '',\n className: rowFlagsColumnCell,\n cell: (row) => {\n return <RowFlagsCell row={row} flags={rowFlags} tApp={tApp} />;\n },\n };\n\n // Ensure we never pick the flags column as \"primary\".\n const withFlags = [flagsColumn, ...inputColumns];\n const hasPrimary = withFlags.some((col) => {\n return col.isPrimary === true;\n });\n\n columns = withFlags;\n if (!hasPrimary) {\n columns = withFlags.map((col, index) => {\n if (index === 1) {\n return { ...col, isPrimary: true };\n }\n return col;\n });\n }\n }\n\n let flagCount = 0;\n if (hasFlags) {\n flagCount = rowFlags.length;\n }\n const flagsWidthPx = computeRowFlagsColumnWidthPx(flagCount);\n const actionsWidthPx = computeActionsColumnWidthPx(actionCount);\n\n // We always include the right-side \"actions\" column in list pages.\n let leftColumnCount = 0;\n if (hasFlags) {\n leftColumnCount = 1;\n }\n const middleCount = columns.length - leftColumnCount - 1;\n\n const middleTracks = columns\n .slice(leftColumnCount, leftColumnCount + Math.max(0, middleCount))\n .map((column) => {\n return resolveTrackBySize(column as DataTableColumn<unknown>, '1fr');\n })\n .join(' ');\n\n let gridTemplateColumns = '';\n if (hasFlags) {\n gridTemplateColumns = `${flagsWidthPx}px ${middleTracks} ${actionsWidthPx}px`;\n } else {\n gridTemplateColumns = `${middleTracks} ${actionsWidthPx}px`;\n }\n\n return { columns, gridTemplateColumns };\n};\n\nconst isRouteAction = (\n action: BackofficeListActionSpec,\n): action is BackofficeEntityRouteActionSpec<null> => {\n return action.kind === 'route';\n};\n\nconst isFormMutationAction = (\n action: BackofficeListActionSpec,\n): action is BackofficeEntityFormMutationActionSpec<null> => {\n return action.kind === 'formMutation';\n};\n\nconst resolveActionVariant = (\n actionVariant: ButtonVariant | undefined,\n index: number,\n): Exclude<ButtonVariant, undefined> => {\n if (actionVariant != null) {\n return actionVariant;\n }\n if (index === 0) {\n return 'primary';\n }\n return 'secondary';\n};\n\nconst resolveRowId = (row: unknown): string | null => {\n if (row == null || typeof row !== 'object') {\n return null;\n }\n if (!('id' in row)) {\n return null;\n }\n const value = (row as { id?: unknown }).id;\n if (typeof value !== 'string') {\n return null;\n }\n const trimmed = value.trim();\n if (trimmed === '') {\n return null;\n }\n return trimmed;\n};\n\nconst buildActionsColumn = (options: {\n ariaLabel: string;\n fallback: string;\n resolveDetailHref: (id: string) => string | null;\n}): DataTableColumn<unknown> => {\n const { ariaLabel, fallback, resolveDetailHref } = options;\n\n return {\n id: 'actions',\n header: '',\n className: pageStyles.actionsColumnCell,\n cell: (row) => {\n const id = resolveRowId(row);\n if (id == null) {\n return fallback;\n }\n const href = resolveDetailHref(id);\n if (href == null) {\n return fallback;\n }\n return (\n <TableCell.Actions>\n <span className={pageStyles.actionTrigger} title={ariaLabel}>\n <LinkButton\n to={href}\n variant=\"icon\"\n size=\"small\"\n aria-label={ariaLabel}\n >\n <EyeSvg width={16} height={16} />\n </LinkButton>\n </span>\n </TableCell.Actions>\n );\n },\n };\n};\n\nconst BackofficeEntityRecordListPage = ({\n config,\n prepared,\n}: BackofficeEntityListPageProps): JSX.Element | null => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const { entities } = useBackofficeConfig();\n const [activeFormActionId, setActiveFormActionId] = useState<string | null>(\n null,\n );\n const environment = useRelayEnvironment();\n\n if (!isRecordListConfig(config)) {\n return null;\n }\n\n const listConfig = config.list;\n const listDefaults = config.listDefaults ??\n listConfig.defaultState ?? { where: null, sort: null };\n const queryData = usePreloadedQuery(listConfig.query, prepared.query);\n const fragmentData = useFragment(listConfig.fragment, queryData as never);\n\n const initialRows = useMemo(() => {\n return listConfig.getRows(fragmentData).map((row) => {\n return listConfig.toRow(row);\n });\n }, [fragmentData, listConfig]);\n\n const initialCursor = useMemo(() => {\n return listConfig.getNextCursor?.(queryData as never) ?? null;\n }, [listConfig, queryData]);\n\n const [rows, setRows] = useState(initialRows);\n const [nextCursor, setNextCursor] = useState<string | null>(initialCursor);\n const [isLoadingMore, setIsLoadingMore] = useState(false);\n const [isRefreshing, setIsRefreshing] = useState(false);\n\n useEffect(() => {\n setRows(initialRows);\n setNextCursor(initialCursor);\n }, [initialCursor, initialRows]);\n\n const { columns, gridTemplateColumns } = useMemo((): {\n columns: readonly DataTableColumn<unknown>[];\n gridTemplateColumns?: string;\n } => {\n const baseColumns = buildDataTableColumns(listConfig.columns, {\n tApp,\n t,\n resolveEntityHref: (entityId, refId) => {\n const entityManifest = entities[entityId];\n if (entityManifest == null) {\n return null;\n }\n return entityManifest.routes.detail(refId);\n },\n });\n const actionsColumn = buildActionsColumn({\n ariaLabel: t('actions.view'),\n fallback: t('common.notAvailable'),\n resolveDetailHref: (id) => {\n return config.routes.detail(id);\n },\n });\n const allColumns = [...baseColumns, actionsColumn];\n return applyListEdgeColumns(allColumns, listConfig.rowFlags, 1, tApp);\n }, [\n config.routes,\n listConfig.columns,\n listConfig.rowFlags,\n entities,\n t,\n tApp,\n ]);\n\n const getRowId = useCallback<GetRowId<unknown>>(\n (row) => {\n return listConfig.getRowId(row);\n },\n [listConfig],\n );\n\n const { state, pushState } = useBackofficeListUrlState(config);\n const resolvedSort = state.sort ?? listDefaults.sort;\n const { pageSize } = BACKOFFICE_LIST_DEFAULTS;\n\n const buildVariables = useCallback(\n (input: {\n where: Record<string, unknown> | null;\n sort: string | null;\n count: number;\n cursor: string | null;\n }) => {\n if (listConfig.buildVariables != null) {\n return listConfig.buildVariables(input as never);\n }\n return input;\n },\n [listConfig],\n );\n\n const requestIdRef = useRef(0);\n const lastRefetchKeyRef = useRef(\n stableListVariablesKey({\n where: listDefaults.where,\n sort: listDefaults.sort,\n count: pageSize,\n }),\n );\n\n const runFetch = useCallback(\n async (input: RecordFetchInput) => {\n const requestId = requestIdRef.current + 1;\n requestIdRef.current = requestId;\n\n if (input.mode === 'append') {\n setIsLoadingMore(true);\n } else {\n setIsRefreshing(true);\n }\n\n try {\n const variables = buildVariables({\n where: input.where,\n sort: input.sort,\n count: input.count,\n cursor: input.cursor,\n });\n\n const response = await fetchQuery(\n environment,\n listConfig.query,\n variables as never,\n { fetchPolicy: RECORD_FETCH_POLICY },\n ).toPromise();\n\n if (response == null || requestIdRef.current !== requestId) {\n return;\n }\n\n const nextRows = listConfig.getRows(response as never).map((row) => {\n return listConfig.toRow(row);\n });\n setRows((prev) => {\n if (input.mode === 'append') {\n return [...prev, ...nextRows];\n }\n return nextRows;\n });\n const cursor = listConfig.getNextCursor?.(response as never) ?? null;\n setNextCursor(cursor);\n } finally {\n if (input.mode === 'append') {\n setIsLoadingMore(false);\n } else {\n setIsRefreshing(false);\n }\n }\n },\n [buildVariables, environment, listConfig],\n );\n\n useEffect(() => {\n const key = stableListVariablesKey({\n where: state.where,\n sort: resolvedSort,\n count: pageSize,\n });\n if (lastRefetchKeyRef.current === key) {\n return;\n }\n lastRefetchKeyRef.current = key;\n runFetch({\n where: state.where,\n sort: resolvedSort,\n count: pageSize,\n cursor: null,\n mode: 'reset',\n }).catch(() => {});\n }, [pageSize, resolvedSort, runFetch, state.where]);\n\n const handleRefresh = useCallback(() => {\n if (isRefreshing) {\n return;\n }\n runFetch({\n where: state.where,\n sort: resolvedSort,\n count: pageSize,\n cursor: null,\n mode: 'reset',\n }).catch(() => {});\n }, [isRefreshing, pageSize, resolvedSort, runFetch, state.where]);\n\n const handleLoadMore = useBackofficeLoadMore({\n hasNext: nextCursor != null,\n isLoadingNext: isLoadingMore,\n loadNext: (count) => {\n if (nextCursor == null) {\n return;\n }\n runFetch({\n where: state.where,\n sort: resolvedSort,\n count,\n cursor: nextCursor,\n mode: 'append',\n }).catch(() => {});\n },\n count: pageSize,\n });\n\n const listActions = useMemo(() => {\n return config.listActions ?? [];\n }, [config.listActions]);\n const visibleActions = useMemo(() => {\n return listActions.filter((action) => {\n if (action.isVisible == null) {\n return true;\n }\n return action.isVisible(null);\n });\n }, [listActions]);\n\n const headerActions = useMemo(() => {\n if (visibleActions.length === 0) {\n return undefined;\n }\n return (\n <div className={pageStyles.headerActions}>\n {visibleActions.map((action, index) => {\n const { variant: actionVariant } = action;\n const label = resolveLabel(action.label, tApp);\n let ariaLabel = label;\n if (action.ariaLabel != null) {\n ariaLabel = resolveLabel(action.ariaLabel, tApp);\n }\n const variant = resolveActionVariant(actionVariant, index);\n const size = action.size ?? 'small';\n const isDisabled = action.isDisabled?.(null) === true;\n\n if (isRouteAction(action)) {\n const href = action.to(null);\n return (\n <LinkButton\n key={action.id}\n to={href}\n variant={variant}\n size={size}\n isDisabled={isDisabled}\n aria-label={ariaLabel}\n >\n {label}\n </LinkButton>\n );\n }\n\n if (isFormMutationAction(action)) {\n return (\n <Button\n key={action.id}\n type=\"button\"\n variant={variant}\n size={size}\n disabled={isDisabled}\n onClick={() => {\n setActiveFormActionId(action.id);\n }}\n aria-label={ariaLabel}\n >\n {label}\n </Button>\n );\n }\n\n return null;\n })}\n </div>\n );\n }, [tApp, visibleActions]);\n\n const activeFormAction = listActions.find((action) => {\n return action.id === activeFormActionId;\n });\n\n return (\n <>\n <BackofficeEntityListScaffold\n config={config}\n state={state}\n pushState={pushState}\n headerActions={headerActions}\n rows={rows}\n columns={columns}\n gridTemplateColumns={gridTemplateColumns}\n getRowId={getRowId}\n hasNextPage={nextCursor != null}\n isLoadingMore={isLoadingMore}\n onLoadMore={handleLoadMore}\n onRefresh={handleRefresh}\n totalCount={null}\n />\n {activeFormAction != null && isFormMutationAction(activeFormAction) && (\n <LazyBackofficeEntityActionFormDialog\n isOpen\n action={activeFormAction}\n node={null}\n onClose={() => {\n setActiveFormActionId(null);\n }}\n onSuccess={handleRefresh}\n />\n )}\n </>\n );\n};\n\nexport const BackofficeEntityListPage = ({\n entityManifest,\n config,\n prepared,\n}: BackofficeEntityListPageProps): JSX.Element | null => {\n const { t: tApp } = useTranslation();\n const breadcrumb = buildEntityListBreadcrumb(config, tApp);\n\n if (isRecordListConfig(config)) {\n return (\n <BackofficeRightPageLayout breadcrumb={breadcrumb}>\n <BackofficeEntityRecordListPage\n entityManifest={entityManifest}\n config={config}\n prepared={prepared}\n />\n </BackofficeRightPageLayout>\n );\n }\n const listConfig = config.list;\n if (listConfig.kind === 'records') {\n return null;\n }\n\n const { t } = useBackofficeReactTranslation();\n const { entities } = useBackofficeConfig();\n const [activeFormActionId, setActiveFormActionId] = useState<string | null>(\n null,\n );\n\n const queryData = usePreloadedQuery(listConfig.query, prepared.query);\n const {\n data: fragmentData,\n loadNext,\n hasNext,\n isLoadingNext,\n refetch,\n } = usePaginationFragment(listConfig.fragment, queryData as never);\n\n const connection = listConfig.getConnection(fragmentData);\n\n const rows = useMemo(() => {\n return connection.edges.map((edge) => {\n return listConfig.toRow(edge.node);\n });\n }, [connection.edges, listConfig]);\n\n const { columns, gridTemplateColumns } = useMemo((): {\n columns: readonly DataTableColumn<unknown>[];\n gridTemplateColumns?: string;\n } => {\n const baseColumns = buildDataTableColumns(listConfig.columns, {\n tApp,\n t,\n resolveEntityHref: (entityId, refId) => {\n const entityManifest = entities[entityId];\n if (entityManifest == null) {\n return null;\n }\n return entityManifest.routes.detail(refId);\n },\n });\n const actionsColumn = buildActionsColumn({\n ariaLabel: t('actions.view'),\n fallback: t('common.notAvailable'),\n resolveDetailHref: (id) => {\n return config.routes.detail(id);\n },\n });\n const allColumns = [...baseColumns, actionsColumn];\n return applyListEdgeColumns(allColumns, listConfig.rowFlags, 1, tApp);\n }, [\n config.routes,\n listConfig.columns,\n listConfig.rowFlags,\n entities,\n t,\n tApp,\n ]);\n\n const getRowId = useCallback<GetRowId<unknown>>(\n (row) => {\n return listConfig.getRowId(row as never);\n },\n [listConfig],\n );\n\n const { state, pushState } = useBackofficeListUrlState(config);\n const listDefaults = config.listDefaults ??\n listConfig.defaultState ?? { where: null, sort: null };\n const resolvedSort = state.sort ?? listDefaults.sort;\n const { pageSize } = BACKOFFICE_LIST_DEFAULTS;\n\n const baseVariables = useMemo(() => {\n return {\n where: state.where,\n sort: resolvedSort,\n count: pageSize,\n cursor: null,\n };\n }, [pageSize, resolvedSort, state.where]);\n\n const { onRefresh } = useBackofficeListRefetch({\n refetch: refetch as never,\n variables: baseVariables,\n defaults: {\n where: listDefaults.where,\n sort: listDefaults.sort,\n count: pageSize,\n cursor: null,\n },\n fetchPolicy: BACKOFFICE_LIST_REFETCH_POLICY,\n buildVariables: listConfig.buildVariables,\n });\n\n const handleLoadMore = useBackofficeLoadMore({\n hasNext,\n isLoadingNext,\n loadNext,\n count: pageSize,\n });\n\n const listActions = useMemo(() => {\n return config.listActions ?? [];\n }, [config.listActions]);\n const visibleActions = useMemo(() => {\n return listActions.filter((action) => {\n if (action.isVisible == null) {\n return true;\n }\n return action.isVisible(null);\n });\n }, [listActions]);\n\n const headerActions = useMemo(() => {\n if (visibleActions.length === 0) {\n return undefined;\n }\n return (\n <div className={pageStyles.headerActions}>\n {visibleActions.map((action, index) => {\n const { variant: actionVariant } = action;\n const label = resolveLabel(action.label, tApp);\n let ariaLabel = label;\n if (action.ariaLabel != null) {\n ariaLabel = resolveLabel(action.ariaLabel, tApp);\n }\n const variant = resolveActionVariant(actionVariant, index);\n const size = action.size ?? 'small';\n const isDisabled = action.isDisabled?.(null) === true;\n\n if (isRouteAction(action)) {\n const href = action.to(null);\n return (\n <LinkButton\n key={action.id}\n to={href}\n variant={variant}\n size={size}\n isDisabled={isDisabled}\n aria-label={ariaLabel}\n >\n {label}\n </LinkButton>\n );\n }\n\n if (isFormMutationAction(action)) {\n return (\n <Button\n key={action.id}\n type=\"button\"\n variant={variant}\n size={size}\n disabled={isDisabled}\n onClick={() => {\n setActiveFormActionId(action.id);\n }}\n aria-label={ariaLabel}\n >\n {label}\n </Button>\n );\n }\n\n return null;\n })}\n </div>\n );\n }, [tApp, visibleActions]);\n\n const activeFormAction = listActions.find((action) => {\n return action.id === activeFormActionId;\n });\n\n return (\n <BackofficeRightPageLayout breadcrumb={breadcrumb}>\n <BackofficeEntityListScaffold\n config={config}\n state={state}\n pushState={pushState}\n headerActions={headerActions}\n rows={rows}\n columns={columns}\n gridTemplateColumns={gridTemplateColumns}\n getRowId={getRowId}\n hasNextPage={hasNext}\n isLoadingMore={isLoadingNext}\n onLoadMore={handleLoadMore}\n onRefresh={onRefresh}\n totalCount={connection.totalCount ?? null}\n />\n {activeFormAction != null && isFormMutationAction(activeFormAction) && (\n <LazyBackofficeEntityActionFormDialog\n isOpen\n action={activeFormAction}\n node={null}\n onClose={() => {\n setActiveFormActionId(null);\n }}\n onSuccess={onRefresh}\n />\n )}\n </BackofficeRightPageLayout>\n );\n};\n\nexport default BackofficeEntityListPage;\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { i as e } from "./environment-BJeJTbIN.js";
2
2
  import { t } from "./useRelayEnvironment-vQ86aW-n.js";
3
- import { n } from "./sprinkles.css.ts.vanilla-n-NK_DwW.js";
3
+ import { n } from "./BackofficeConfigContext-R0t1owTI.js";
4
4
  import { a as r, i, n as a, r as o, t as s } from "./sidebarUtils-CuwJ_3mD.js";
5
5
  import { n as c, t as l } from "./useBackofficeReactTranslation-WfXU8kCf.js";
6
6
  import { t as u } from "./BackofficeTopbarPortalContext-iD7dm4_h.js";
@@ -103,7 +103,7 @@ var I = "backoffice.sidebar.pins.v1", L = (e) => {
103
103
  });
104
104
  }, [])
105
105
  };
106
- }, B = "_1xws1b01 _1xws1b00 vncd899jf vncd89co vncd89dnx vncd89two vncd89c66 vncd891rf vncd8912f vncd891px vncd89l9f vncd89uzj vncd89v8r vncd89v vncd8978 vncd896x vncd897k", V = (e, t) => e == null ? t ?? null : /* @__PURE__ */ P(e, {
106
+ }, B = "_1xws1b00 txvbqb9jf txvbqbco txvbqbdnx txvbqbtwo txvbqbc66 txvbqb1rf txvbqb12f txvbqb1px txvbqbl9f txvbqbuzj txvbqbv8r txvbqbv txvbqb78 txvbqb6x txvbqb7k", V = (e, t) => e == null ? t ?? null : /* @__PURE__ */ P(e, {
107
107
  width: 18,
108
108
  height: 18,
109
109
  "aria-hidden": "true"
@@ -275,7 +275,7 @@ function ie(e) {
275
275
  }
276
276
  //#endregion
277
277
  //#region src/components/backoffice/routing/backofficeContentError.css.ts
278
- var H = "_1xfx8p60 vncd899io vncd89ai6 vncd89u6f", U = "_1xfx8p61 vncd89wx", W = (e) => {
278
+ var H = "txvbqb9io txvbqbai6 txvbqbu6f", U = "txvbqbwx", W = (e) => {
279
279
  if (e instanceof Error) {
280
280
  let t = e.message.trim();
281
281
  return t.length > 0 ? t : null;
@@ -303,7 +303,7 @@ var H = "_1xfx8p60 vncd899io vncd89ai6 vncd89u6f", U = "_1xfx8p61 vncd89wx", W =
303
303
  children: r
304
304
  })
305
305
  });
306
- }, K = "_1f7vqmu0 vncd899io vncd89ai6 vncd89aoo vncd89u6f vncd89jr6", q = "_1f7vqmu1 vncd89jef", J = "_1f7vqmu2 vncd899ix vncd89aoo vncd89c0o", Y = "_1f7vqmu3 vncd899io vncd89ai6 vncd89aof vncd89laf vncd89jmx vncd891rx vncd891co vncd891qf vncd89wo vncd89v2v", X = () => /* @__PURE__ */ F("div", {
306
+ }, K = "txvbqb9io txvbqbai6 txvbqbaoo txvbqbu6f txvbqbjr6", q = "txvbqbjef", J = "txvbqb9ix txvbqbaoo txvbqbc0o", Y = "txvbqb9io txvbqbai6 txvbqbaof txvbqblaf txvbqbjmx txvbqb1rx txvbqb1co txvbqb1qf txvbqbwo txvbqbv2v", X = () => /* @__PURE__ */ F("div", {
307
307
  className: K,
308
308
  role: "status",
309
309
  "aria-live": "polite",
@@ -341,7 +341,7 @@ var H = "_1xfx8p60 vncd899io vncd89ai6 vncd89u6f", U = "_1xfx8p61 vncd89wx", W =
341
341
  }, `content-skeleton-${t}`))
342
342
  })
343
343
  ]
344
- }), Z = "_2w9m800 vncd899io vncd89ai6 vncd89jr6 vncd89u6f vncd89k4x", ae = ({ children: e }) => /* @__PURE__ */ P("div", {
344
+ }), Z = "txvbqb9io txvbqbai6 txvbqbjr6 txvbqbu6f txvbqbk4x", ae = ({ children: e }) => /* @__PURE__ */ P("div", {
345
345
  className: Z,
346
346
  children: /* @__PURE__ */ P(c, {
347
347
  fallback: ({ error: e, reset: t }) => /* @__PURE__ */ P(G, {
@@ -482,4 +482,4 @@ var H = "_1xfx8p60 vncd899io vncd89ai6 vncd89u6f", U = "_1xfx8p61 vncd89wx", W =
482
482
  //#endregion
483
483
  export { ce as BackofficeLayoutPage, ce as default };
484
484
 
485
- //# sourceMappingURL=BackofficeLayoutPage-k9OkLfXb.js.map
485
+ //# sourceMappingURL=BackofficeLayoutPage-DpvTzwtK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BackofficeLayoutPage-DpvTzwtK.js","names":[],"sources":["../../src/hooks/useBackofficeSidebarPins.ts","../../src/hooks/useSidebarGroupCollapse.ts","../../src/components/backoffice/layout/backofficeSidebarActions.css.ts","../../src/components/backoffice/layout/buildSidebarSections.tsx","../../src/components/backoffice/routing/backofficeContentError.css.ts","../../src/components/backoffice/routing/BackofficeContentError.tsx","../../src/components/backoffice/routing/backofficeContentFallback.css.ts","../../src/components/backoffice/routing/BackofficeContentFallback.tsx","../../src/components/backoffice/routing/backofficeContentBoundary.css.ts","../../src/components/backoffice/routing/BackofficeContentBoundary.tsx","../../src/components/backoffice/layout/mapViewerToSidebarProfileView.ts","../../src/pages/BackofficeLayoutPage.tsx"],"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 = (pins: readonly string[], validIds: Set<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\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 storageKey?: string;\n visibleEntityIds: readonly string[];\n};\n\nexport const useBackofficeSidebarPins = (\n input: UseBackofficeSidebarPinsInput,\n): SidebarPinsState => {\n const { storageKey = DEFAULT_STORAGE_KEY, visibleEntityIds } = input;\n const validIds = useMemo(() => {\n return new Set(visibleEntityIds);\n }, [visibleEntityIds]);\n\n const [pins, setPins] = useState<string[]>(() => {\n const stored = readPinsFromStorage(storageKey);\n return normalizePins(stored, validIds);\n });\n\n useEffect(() => {\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 }, [validIds]);\n\n useEffect(() => {\n const stored = readPinsFromStorage(storageKey);\n setPins(normalizePins(stored, validIds));\n }, [storageKey, validIds]);\n\n useEffect(() => {\n if (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 }, [pins, storageKey]);\n\n const pinsSet = useMemo(() => {\n return new Set(pins);\n }, [pins]);\n\n const pin = useCallback(\n (id: string) => {\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 [validIds],\n );\n\n const unpin = useCallback((id: string) => {\n setPins((prev) => {\n return prev.filter((entry) => {\n return entry !== id;\n });\n });\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((fromId: string, toId: string) => {\n if (fromId === toId) {\n return;\n }\n setPins((prev) => {\n const fromIndex = prev.indexOf(fromId);\n const toIndex = prev.indexOf(toId);\n if (fromIndex === -1 || toIndex === -1) {\n return prev;\n }\n if (fromIndex === toIndex) {\n return prev;\n }\n const next = [...prev];\n next.splice(fromIndex, 1);\n next.splice(toIndex, 0, fromId);\n return next;\n });\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 default useBackofficeSidebarPins;\n","import { useCallback, useEffect, useMemo, useState } from 'react';\n\nexport type SidebarGroupCollapseState = Record<string, boolean | undefined>;\n\nexport type UseSidebarGroupCollapseInput = {\n groupIds: readonly string[];\n activeGroupId?: string | null;\n};\n\nconst buildInitialState = (\n groupIds: readonly string[],\n activeGroupId?: string | null,\n): SidebarGroupCollapseState => {\n const state: SidebarGroupCollapseState = {};\n groupIds.forEach((groupId) => {\n state[groupId] = true;\n });\n if (activeGroupId != null && groupIds.includes(activeGroupId)) {\n state[activeGroupId] = false;\n }\n return state;\n};\n\nexport const useSidebarGroupCollapse = (\n input: UseSidebarGroupCollapseInput,\n): {\n collapsedByGroupId: SidebarGroupCollapseState;\n setCollapsed: (groupId: string, collapsed: boolean) => void;\n} => {\n const { groupIds, activeGroupId } = input;\n\n const groupIdList = useMemo(() => {\n return [...groupIds];\n }, [groupIds]);\n\n const [collapsedByGroupId, setCollapsedByGroupId] =\n useState<SidebarGroupCollapseState>(() => {\n return buildInitialState(groupIdList, activeGroupId);\n });\n\n useEffect(() => {\n setCollapsedByGroupId((prev) => {\n const next: SidebarGroupCollapseState = {};\n\n groupIdList.forEach((groupId) => {\n const existing = prev[groupId];\n next[groupId] = existing ?? true;\n });\n\n if (activeGroupId != null && groupIdList.includes(activeGroupId)) {\n next[activeGroupId] = false;\n }\n\n return next;\n });\n }, [activeGroupId, groupIdList]);\n\n useEffect(() => {\n if (activeGroupId == null) {\n return;\n }\n setCollapsedByGroupId((prev) => {\n if (prev[activeGroupId] === false) {\n return prev;\n }\n return {\n ...prev,\n [activeGroupId]: false,\n };\n });\n }, [activeGroupId]);\n\n const setCollapsed = useCallback((groupId: string, collapsed: boolean) => {\n setCollapsedByGroupId((prev) => {\n if (prev[groupId] === collapsed) {\n return prev;\n }\n return {\n ...prev,\n [groupId]: collapsed,\n };\n });\n }, []);\n\n return {\n collapsedByGroupId,\n setCollapsed,\n };\n};\n\nexport default useSidebarGroupCollapse;\n","import { style } from '@vanilla-extract/css';\n\nimport { sprinkles, vars } from '@plumile/ui';\n\nexport const actionButton = style([\n sprinkles({\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: 6,\n height: 6,\n borderRadius: 'md',\n borderWidth: 0,\n borderStyle: 'none',\n padding: 0,\n backgroundColor: 'transparent',\n color: 'textSecondary',\n cursor: 'pointer',\n transitionProperty: 'colors',\n transitionDuration: 150,\n transitionTimingFunction: 'ease',\n }),\n {\n selectors: {\n '&:hover': {\n backgroundColor: vars.colors.surfaceMuted,\n color: vars.colors.text,\n },\n '&:focus-visible': {\n outline: `2px solid ${vars.colors['blue-500']}`,\n outlineOffset: 2,\n },\n },\n },\n]);\n","import { type DragEvent, type ReactNode } from 'react';\nimport type { TFunction } from 'i18next';\n\nimport type { BackofficeEntityManifestMap } from '@plumile/backoffice-core/types.js';\nimport type {\n BackofficeSidebarConfig,\n BackofficeSidebarItemDescriptor,\n BackofficeIconComponent,\n} from '../../../provider/types.js';\nimport {\n type AdminSidebarSection,\n type SidebarNavSectionItem,\n GripDotsSvg,\n PinFilledSvg,\n PinSvg,\n SidebarHomeSvg,\n SidebarTasksSvg,\n} from '@plumile/ui';\nimport type { SidebarGroupCollapseState } from '../../../hooks/useSidebarGroupCollapse.js';\nimport * as styles from './backofficeSidebarActions.css.js';\nimport {\n buildEntityGroupLookup,\n isActivePath,\n resolveLabel,\n resolveSidebarGroups,\n} from './sidebarUtils.js';\n\nconst renderIcon = (\n Icon?: BackofficeIconComponent,\n fallback?: ReactNode,\n): ReactNode => {\n if (Icon != null) {\n return <Icon width={18} height={18} aria-hidden=\"true\" />;\n }\n return fallback ?? null;\n};\n\nexport type BuildSidebarSectionsInput = {\n basePath: string;\n pathname: string;\n entities: BackofficeEntityManifestMap;\n sidebar?: BackofficeSidebarConfig;\n permissions: unknown;\n searchQuery?: string;\n tApp: TFunction;\n t: TFunction;\n pinnedEntityIds?: readonly string[];\n onTogglePin?: (entityId: string) => void;\n onReorderPin?: (fromId: string, toId: string) => void;\n collapsedByGroupId?: SidebarGroupCollapseState;\n onGroupCollapsedChange?: (groupId: string, collapsed: boolean) => void;\n};\n\n/**\n * Builds the sidebar sections for the backoffice layout.\n */\nexport function buildSidebarSections(\n input: BuildSidebarSectionsInput,\n): readonly AdminSidebarSection[] {\n const {\n basePath,\n pathname,\n entities,\n sidebar,\n permissions,\n searchQuery,\n tApp,\n t,\n pinnedEntityIds = [],\n onTogglePin,\n onReorderPin,\n collapsedByGroupId,\n onGroupCollapsedChange,\n } = input;\n\n const groups = resolveSidebarGroups(entities, sidebar);\n const entries = Object.entries(groups);\n const pinnedSet = new Set(pinnedEntityIds);\n const pinLabel = t('sidebar.actions.pin');\n const unpinLabel = t('sidebar.actions.unpin');\n const reorderLabel = t('sidebar.actions.reorder');\n const entityGroupLookup = buildEntityGroupLookup(groups);\n const normalizedQuery = searchQuery?.trim().toLowerCase() ?? '';\n\n const renderPinAction = (entityId: string): ReactNode | null => {\n if (onTogglePin == null) {\n return null;\n }\n const isPinned = pinnedSet.has(entityId);\n let label = pinLabel;\n let Icon = PinSvg;\n if (isPinned) {\n label = unpinLabel;\n Icon = PinFilledSvg;\n }\n\n return (\n <button\n type=\"button\"\n className={styles.actionButton}\n aria-pressed={isPinned}\n aria-label={label}\n title={label}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n onTogglePin(entityId);\n }}\n >\n <Icon width={14} height={14} aria-hidden=\"true\" />\n </button>\n );\n };\n\n const buildEntityItem = (inputItem: {\n entityId: string;\n groupId?: string;\n groupIcon?: BackofficeIconComponent;\n enableReorder?: boolean;\n }): SidebarNavSectionItem | null => {\n const { entityId, groupId, groupIcon, enableReorder } = inputItem;\n const config = entities[entityId];\n if (config == null) {\n return null;\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 const isEntityVisible = sidebar?.isItemVisible?.(descriptor, permissions);\n if (isEntityVisible === false) {\n return null;\n }\n\n if (config.kind === 'tool') {\n const label = resolveLabel(config.label, tApp);\n if (\n normalizedQuery !== '' &&\n !label.toLowerCase().includes(normalizedQuery)\n ) {\n return null;\n }\n return {\n id: `tool-${entityId}`,\n data: {\n kind: 'tool',\n id: entityId,\n groupId,\n },\n label,\n href: config.routes.list,\n icon: renderIcon(\n groupIcon,\n <SidebarTasksSvg width={18} height={18} aria-hidden=\"true\" />,\n ),\n isActive: isActivePath(pathname, config.routes.list),\n ariaLabel: label,\n actionSlot: renderPinAction(entityId),\n };\n }\n\n if (!config.hasList) {\n return null;\n }\n\n const label = resolveLabel(config.label, tApp);\n if (\n normalizedQuery !== '' &&\n !label.toLowerCase().includes(normalizedQuery)\n ) {\n return null;\n }\n\n let dragHandleSlot: ReactNode | undefined;\n let onDragStart: ((event: DragEvent) => void) | undefined;\n let onDragOver: ((event: DragEvent) => void) | undefined;\n let onDrop: ((event: DragEvent) => void) | undefined;\n let draggable = false;\n\n if (enableReorder === true && onReorderPin != null) {\n draggable = true;\n dragHandleSlot = (\n <GripDotsSvg width={14} height={14} aria-hidden=\"true\" />\n );\n onDragStart = (event) => {\n const { dataTransfer } = event;\n dataTransfer.effectAllowed = 'move';\n dataTransfer.setData('text/plain', entityId);\n };\n onDragOver = (event) => {\n event.preventDefault();\n const { dataTransfer } = event;\n dataTransfer.dropEffect = 'move';\n };\n onDrop = (event) => {\n event.preventDefault();\n const fromId = event.dataTransfer.getData('text/plain');\n if (fromId === '' || fromId === entityId) {\n return;\n }\n onReorderPin(fromId, entityId);\n };\n }\n\n let dragHandleLabel: string | undefined;\n if (dragHandleSlot != null) {\n dragHandleLabel = reorderLabel;\n }\n\n return {\n id: entityId,\n data: {\n kind: 'entity',\n id: entityId,\n groupId,\n },\n label,\n href: config.routes.list,\n icon: renderIcon(\n groupIcon,\n <SidebarTasksSvg width={18} height={18} aria-hidden=\"true\" />,\n ),\n isActive: isActivePath(pathname, config.routes.list),\n ariaLabel: label,\n actionSlot: renderPinAction(entityId),\n dragHandleSlot,\n dragHandleLabel,\n draggable,\n onDragStart,\n onDragOver,\n onDrop,\n };\n };\n\n const sections: AdminSidebarSection[] = [];\n\n if (pinnedEntityIds.length > 0) {\n const pinnedItems = pinnedEntityIds\n .map((entityId) => {\n const groupMeta = entityGroupLookup.get(entityId);\n return buildEntityItem({\n entityId,\n groupId: groupMeta?.groupId,\n groupIcon: groupMeta?.icon,\n enableReorder: true,\n });\n })\n .filter((item): item is SidebarNavSectionItem => {\n return item != null;\n });\n\n if (pinnedItems.length > 0) {\n sections.push({\n id: 'pinned',\n title: t('sidebar.sections.pinned'),\n items: pinnedItems,\n collapsible: false,\n });\n }\n }\n\n entries.forEach(([groupId, group], index) => {\n if (group.isVisible != null && !group.isVisible(permissions)) {\n return;\n }\n\n const items: SidebarNavSectionItem[] = [];\n\n if (index === 0) {\n const dashboardDescriptor: BackofficeSidebarItemDescriptor = {\n kind: 'dashboard',\n id: 'dashboard',\n };\n const isDashboardVisible = sidebar?.isItemVisible?.(\n dashboardDescriptor,\n permissions,\n );\n if (isDashboardVisible !== false) {\n const dashboardLabel = t('sidebar.items.dashboard');\n if (\n normalizedQuery !== '' &&\n !dashboardLabel.toLowerCase().includes(normalizedQuery)\n ) {\n return;\n }\n items.push({\n id: 'dashboard',\n data: {\n kind: 'dashboard',\n id: 'dashboard',\n groupId,\n },\n label: dashboardLabel,\n href: basePath,\n icon: renderIcon(\n undefined,\n <SidebarHomeSvg width={18} height={18} aria-hidden=\"true\" />,\n ),\n isActive: isActivePath(pathname, basePath),\n ariaLabel: t('sidebar.items.dashboard'),\n });\n }\n }\n\n if (group.entities != null) {\n group.entities.forEach((entityId) => {\n const item = buildEntityItem({\n entityId,\n groupId,\n groupIcon: group.icon,\n });\n if (item != null) {\n items.push(item);\n }\n });\n }\n\n if (items.length === 0) {\n return;\n }\n\n let title: string | undefined;\n if (group.title != null) {\n title = resolveLabel(group.title, tApp);\n }\n\n const isCollapsed = collapsedByGroupId?.[groupId];\n let onCollapsedChange: ((collapsed: boolean) => void) | undefined;\n if (onGroupCollapsedChange != null) {\n onCollapsedChange = (collapsed: boolean) => {\n onGroupCollapsedChange(groupId, collapsed);\n };\n }\n\n sections.push({\n id: groupId,\n title,\n items,\n collapsible: true,\n defaultCollapsed: true,\n isCollapsed,\n onCollapsedChange,\n });\n });\n\n return sections;\n}\n","import { sprinkles } from '@plumile/ui';\n\nexport const root = sprinkles({\n display: 'flex',\n flexDirection: 'column',\n width: 'full',\n});\n\nexport const banner = sprinkles({\n borderColor: 'borderStrong',\n});\n","import { type JSX } from 'react';\n\nimport { Button, InlineBanner } from '@plumile/ui';\nimport { useBackofficeReactTranslation } from '../../../i18n/useBackofficeReactTranslation.js';\n\nimport * as styles from './backofficeContentError.css.js';\n\ntype BackofficeContentErrorProps = {\n error: unknown;\n onRetry: () => void;\n};\n\nconst resolveErrorMessage = (error: unknown): string | null => {\n if (error instanceof Error) {\n const message = error.message.trim();\n if (message.length > 0) {\n return message;\n }\n return null;\n }\n if (typeof error === 'string') {\n const message = error.trim();\n if (message.length > 0) {\n return message;\n }\n return null;\n }\n return null;\n};\n\nexport const BackofficeContentError = ({\n error,\n onRetry,\n}: BackofficeContentErrorProps): JSX.Element => {\n const { t } = useBackofficeReactTranslation();\n const description = resolveErrorMessage(error);\n\n return (\n <div className={styles.root} role=\"alert\">\n <InlineBanner\n tone=\"danger\"\n className={styles.banner}\n actions={\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={onRetry}\n >\n {t('common.actions.retry')}\n </Button>\n }\n >\n {description}\n </InlineBanner>\n </div>\n );\n};\n\nexport default BackofficeContentError;\n","import { sprinkles } from '@plumile/ui';\n\nexport const container = sprinkles({\n display: 'flex',\n flexDirection: 'column',\n gap: 4,\n width: 'full',\n minHeight: 'full',\n});\n\nexport const title = sprinkles({\n maxWidth: 'md',\n});\n\nexport const grid = sprinkles({\n display: 'grid',\n gap: 4,\n gridTemplateColumns: 'autoFitMinmax240',\n});\n\nexport const card = sprinkles({\n display: 'flex',\n flexDirection: 'column',\n gap: 3,\n padding: 4,\n minHeight: 44,\n borderRadius: 'xl',\n borderWidth: 'default',\n borderStyle: 'solid',\n borderColor: 'borderSubtle',\n backgroundColor: 'surfaceMuted',\n});\n","import { type JSX } from 'react';\n\nimport { Skeleton } from '@plumile/ui';\n\nimport * as styles from './backofficeContentFallback.css.js';\n\nexport const BackofficeContentFallback = (): JSX.Element => {\n return (\n <div\n className={styles.container}\n role=\"status\"\n aria-live=\"polite\"\n aria-busy=\"true\"\n >\n <Skeleton variant=\"text\" width=\"38%\" className={styles.title} />\n <Skeleton variant=\"text\" width=\"62%\" />\n <div className={styles.grid}>\n {Array.from({ length: 4 }, (_, index) => {\n return (\n <div key={`content-skeleton-${index}`} className={styles.card}>\n <Skeleton variant=\"text\" width=\"46%\" />\n <Skeleton variant=\"text\" width=\"82%\" lines={2} />\n <Skeleton variant=\"block\" width=\"100%\" height={120} />\n </div>\n );\n })}\n </div>\n </div>\n );\n};\n\nexport default BackofficeContentFallback;\n","import { sprinkles } from '@plumile/ui';\n\nexport const root = sprinkles({\n display: 'flex',\n flexDirection: 'column',\n minHeight: 'full',\n width: 'full',\n minWidth: 0,\n});\n","import { Suspense, type JSX, type ReactNode } from 'react';\n\nimport { BackofficeErrorBoundary } from '../errors/BackofficeErrorBoundary.js';\n\nimport { BackofficeContentError } from './BackofficeContentError.js';\nimport { BackofficeContentFallback } from './BackofficeContentFallback.js';\nimport * as styles from './backofficeContentBoundary.css.js';\n\nexport type BackofficeContentBoundaryProps = {\n children: ReactNode;\n};\n\nexport const BackofficeContentBoundary = ({\n children,\n}: BackofficeContentBoundaryProps): JSX.Element => {\n return (\n <div className={styles.root}>\n <BackofficeErrorBoundary\n fallback={({ error, reset }) => {\n return <BackofficeContentError error={error} onRetry={reset} />;\n }}\n >\n <Suspense fallback={<BackofficeContentFallback />}>{children}</Suspense>\n </BackofficeErrorBoundary>\n </div>\n );\n};\n\nexport default BackofficeContentBoundary;\n","import type { BackofficeSidebarProfileViewer } from '@plumile/ui';\n\nexport type BackofficeViewerIdentity = {\n id: string;\n firstName: string;\n lastName: string;\n email: string;\n initials: string;\n};\n\ntype MapViewerToSidebarProfileViewInput = {\n viewer: BackofficeViewerIdentity | null | undefined;\n unknownUserLabel: string;\n};\n\nconst sanitizeToken = (value: string | null | undefined): string => {\n return value?.trim() ?? '';\n};\n\nexport const mapViewerToSidebarProfileView = ({\n viewer,\n unknownUserLabel,\n}: MapViewerToSidebarProfileViewInput): BackofficeSidebarProfileViewer => {\n const firstName = sanitizeToken(viewer?.firstName);\n const lastName = sanitizeToken(viewer?.lastName);\n const joinedDisplayName = [firstName, lastName]\n .filter((token) => {\n return token !== '';\n })\n .join(' ')\n .trim();\n let displayName = joinedDisplayName;\n if (displayName === '') {\n displayName = unknownUserLabel;\n }\n\n const email = sanitizeToken(viewer?.email);\n const initialsToken = sanitizeToken(viewer?.initials);\n let initials = initialsToken;\n if (initials === '') {\n initials = '?';\n }\n\n const ariaParts = [displayName];\n if (email !== '') {\n ariaParts.push(email);\n }\n\n return {\n displayName,\n email,\n initials,\n ariaLabel: ariaParts.join(' - '),\n };\n};\n\nexport default mapViewerToSidebarProfileView;\n","import {\n useMemo,\n type JSX,\n type ReactNode,\n useCallback,\n useContext,\n useState,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n commitMutation,\n usePreloadedQuery,\n type PreloadedQuery,\n} from 'react-relay';\nimport type {\n GraphQLTaggedNode,\n MutationParameters,\n OperationType,\n} from 'relay-runtime';\nimport { RoutingContext, useLocation } from '@plumile/router';\n\nimport {\n AdminShellLayout,\n BackofficeSidebarProfileMenu,\n EnvironmentBadge,\n GlobalSearchInput,\n ToastProvider,\n} from '@plumile/ui';\n\nimport { useBackofficeReactTranslation } from '../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeConfig } from '../provider/BackofficeConfigContext.js';\nimport type { LogoutResponse, LogoutVariables } from '../hooks/useAuth.js';\nimport { useBackofficeSidebarPins } from '../hooks/useBackofficeSidebarPins.js';\nimport { useSidebarGroupCollapse } from '../hooks/useSidebarGroupCollapse.js';\nimport { buildSidebarSections } from '../components/backoffice/layout/buildSidebarSections.js';\nimport { BackofficeContentBoundary } from '../components/backoffice/routing/BackofficeContentBoundary.js';\nimport {\n resolveSidebarGroups,\n resolveVisibleEntityIds,\n} from '../components/backoffice/layout/sidebarUtils.js';\nimport { BackofficeTopbarPortalContextProvider } from '../components/backoffice/layout/breadcrumb/BackofficeTopbarPortalContext.js';\nimport {\n mapViewerToSidebarProfileView,\n type BackofficeViewerIdentity,\n} from '../components/backoffice/layout/mapViewerToSidebarProfileView.js';\nimport { resetRelayStore } from '../relay/environment.js';\nimport { useRelayEnvironment } from '../relay/useRelayEnvironment.js';\nimport { getBackofficeLoginPath } from '../router/backofficeAuthPaths.js';\n\nexport type BackofficeLayoutPageProps = {\n children: ReactNode;\n permissionsQuery?: GraphQLTaggedNode;\n prepared?: PreloadedQuery<OperationType> | null;\n authStatus?: {\n isLoggedIn?: boolean | null;\n me?: BackofficeViewerIdentity | null;\n } | null;\n activeGroupId?: string | null;\n};\n\ntype LayoutShellProps = {\n children: ReactNode;\n permissions: unknown;\n authStatus?: {\n isLoggedIn?: boolean | null;\n me?: BackofficeViewerIdentity | null;\n } | null;\n activeGroupId?: string | null;\n};\n\nconst BackofficeLayoutShell = ({\n children,\n permissions,\n authStatus,\n activeGroupId,\n}: LayoutShellProps): JSX.Element => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const { pathname } = useLocation();\n const routing = useContext(RoutingContext);\n const relayEnvironment = useRelayEnvironment();\n const {\n auth: authConfig,\n basePath,\n entities,\n sidebar,\n } = useBackofficeConfig();\n const [sidebarQuery, setSidebarQuery] = useState('');\n const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(false);\n const [isSigningOut, setIsSigningOut] = useState(false);\n const [topbarTarget, setTopbarTarget] = useState<HTMLDivElement | null>(null);\n\n const groups = useMemo(() => {\n return resolveSidebarGroups(entities, sidebar);\n }, [entities, sidebar]);\n\n const groupIds = useMemo(() => {\n return Object.keys(groups);\n }, [groups]);\n\n const visibleEntityIds = useMemo(() => {\n return resolveVisibleEntityIds(groups, entities, sidebar, permissions);\n }, [entities, groups, permissions, sidebar]);\n\n const {\n pins,\n toggle: togglePin,\n reorder: reorderPin,\n } = useBackofficeSidebarPins({ visibleEntityIds });\n\n const { collapsedByGroupId, setCollapsed } = useSidebarGroupCollapse({\n groupIds,\n activeGroupId,\n });\n\n const sections = useMemo(() => {\n return buildSidebarSections({\n basePath,\n pathname,\n entities,\n sidebar,\n permissions,\n searchQuery: sidebarQuery,\n tApp,\n t,\n pinnedEntityIds: pins,\n onTogglePin: togglePin,\n onReorderPin: reorderPin,\n collapsedByGroupId,\n onGroupCollapsedChange: setCollapsed,\n });\n }, [\n basePath,\n collapsedByGroupId,\n entities,\n pathname,\n permissions,\n pins,\n reorderPin,\n setCollapsed,\n sidebar,\n sidebarQuery,\n t,\n tApp,\n togglePin,\n ]);\n\n const environment = useMemo(() => {\n const meta = import.meta as unknown as { env?: Record<string, unknown> };\n if (meta.env?.DEV === true) {\n return 'dev' as const;\n }\n return 'prod' as const;\n }, []);\n\n const handleSignOut = useCallback(() => {\n if (isSigningOut) {\n return;\n }\n\n type LogoutMutation = MutationParameters & {\n response: LogoutResponse;\n variables: LogoutVariables;\n };\n\n setIsSigningOut(true);\n\n const runSignOut = async (): Promise<void> => {\n try {\n const config = await authConfig.logout.load();\n await new Promise<void>((resolve, reject) => {\n commitMutation<LogoutMutation>(relayEnvironment, {\n mutation: config.logoutMutation,\n variables: {},\n onCompleted: () => {\n resolve();\n },\n onError: (error) => {\n reject(error);\n },\n });\n });\n localStorage.removeItem('auth_token');\n localStorage.removeItem('remember_me');\n resetRelayStore();\n routing?.history.push({ pathname: getBackofficeLoginPath(basePath) });\n } finally {\n setIsSigningOut(false);\n }\n };\n\n runSignOut().catch(() => {\n /* noop */\n });\n }, [authConfig.logout, basePath, isSigningOut, relayEnvironment, routing]);\n\n const viewer = authStatus?.me ?? null;\n const sidebarProfile = useMemo(() => {\n return mapViewerToSidebarProfileView({\n viewer,\n unknownUserLabel: t('sidebar.profile.unknownUser'),\n });\n }, [t, viewer]);\n\n const sidebarFooter = (\n <BackofficeSidebarProfileMenu\n collapsed={isSidebarCollapsed}\n viewer={sidebarProfile}\n labels={{\n sectionTitle: t('sidebar.profile.title'),\n menuAriaLabel: t('sidebar.profile.menuAriaLabel'),\n signOut: t('sidebar.profile.actions.signOut'),\n }}\n onSignOut={handleSignOut}\n isSigningOut={isSigningOut}\n />\n );\n\n let contentNode: JSX.Element | null = null;\n if (topbarTarget != null) {\n contentNode = (\n <BackofficeContentBoundary>{children}</BackofficeContentBoundary>\n );\n }\n\n return (\n <ToastProvider>\n <AdminShellLayout\n sidebar={{\n sections,\n header: <EnvironmentBadge environment={environment} />,\n search: (\n <GlobalSearchInput\n value={sidebarQuery}\n onChange={setSidebarQuery}\n placeholder={t('sidebar.search.placeholder')}\n ariaLabel={t('sidebar.search.placeholder')}\n />\n ),\n footer: sidebarFooter,\n isCollapsed: isSidebarCollapsed,\n onCollapsedChange: setIsSidebarCollapsed,\n }}\n topbar={{\n breadcrumb: <div ref={setTopbarTarget} />,\n }}\n >\n <BackofficeTopbarPortalContextProvider value={{ target: topbarTarget }}>\n {contentNode}\n </BackofficeTopbarPortalContextProvider>\n </AdminShellLayout>\n </ToastProvider>\n );\n};\n\ntype LayoutWithPermissionsProps = {\n children: ReactNode;\n permissionsQuery: GraphQLTaggedNode;\n prepared: PreloadedQuery<OperationType>;\n authStatus?: {\n isLoggedIn?: boolean | null;\n me?: BackofficeViewerIdentity | null;\n } | null;\n activeGroupId?: string | null;\n};\n\nconst LayoutWithPermissions = ({\n children,\n permissionsQuery,\n prepared,\n authStatus,\n activeGroupId,\n}: LayoutWithPermissionsProps): JSX.Element => {\n const permissions = usePreloadedQuery(permissionsQuery, prepared);\n\n return (\n <BackofficeLayoutShell\n permissions={permissions}\n authStatus={authStatus}\n activeGroupId={activeGroupId}\n >\n {children}\n </BackofficeLayoutShell>\n );\n};\n\nexport const BackofficeLayoutPage = ({\n children,\n permissionsQuery,\n prepared,\n authStatus,\n activeGroupId,\n}: BackofficeLayoutPageProps): JSX.Element => {\n if (permissionsQuery != null && prepared != null) {\n return (\n <LayoutWithPermissions\n permissionsQuery={permissionsQuery}\n prepared={prepared}\n authStatus={authStatus}\n activeGroupId={activeGroupId}\n >\n {children}\n </LayoutWithPermissions>\n );\n }\n\n return (\n <BackofficeLayoutShell\n permissions={null}\n authStatus={authStatus}\n activeGroupId={activeGroupId}\n >\n {children}\n </BackofficeLayoutShell>\n );\n};\n\nexport default BackofficeLayoutPage;\n"],"mappings":"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"}
@@ -1,14 +1,14 @@
1
1
  import "./environment-BJeJTbIN.js";
2
2
  import { t as e } from "./useRelayEnvironment-vQ86aW-n.js";
3
- import { n as t } from "./sprinkles.css.ts.vanilla-n-NK_DwW.js";
4
- import "./loginPage.css-BDQJNcSr.js";
5
- import "./useAuth-AczFS-oL.js";
6
- import { n, t as r } from "./synchronizeAuthStatusQuery-lLR0XFew.js";
7
- import "./AuthPanel-ttoH9YxE.js";
3
+ import { n as t } from "./BackofficeConfigContext-R0t1owTI.js";
4
+ import "./loginPage.css-4M4PrzUn.js";
5
+ import "./useAuth-DzWJXJ_9.js";
6
+ import { n, t as r } from "./synchronizeAuthStatusQuery-Ba776lwa.js";
7
+ import "./AuthPanel-Co626p7A.js";
8
8
  import "./mutationResult-CcQMY13J.js";
9
- import { t as i } from "./useBackofficeAuth-BHteJQzA.js";
9
+ import { t as i } from "./useBackofficeAuth-L9k9i9BI.js";
10
10
  import { n as a } from "./backofficeAuthPaths-BiJvoI5Q.js";
11
- import { t as o } from "./useBackofficeLazyValue-B0-ckL6e.js";
11
+ import { t as o } from "./useBackofficeLazyValue-Dnii1_dE.js";
12
12
  import { useCallback as s, useContext as c, useRef as l } from "react";
13
13
  import { RoutingContext as u } from "@plumile/router";
14
14
  import * as d from "react-relay";
@@ -47,4 +47,4 @@ var { usePreloadedQuery: p } = d, m = ({ prepared: d }) => {
47
47
  //#endregion
48
48
  export { m as BackofficeLoginPage, m as default };
49
49
 
50
- //# sourceMappingURL=BackofficeLoginPage-C64BcxMw.js.map
50
+ //# sourceMappingURL=BackofficeLoginPage-BeihjFO2.js.map