@plumile/backoffice-react 0.1.114 → 0.1.116

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.
@@ -6,30 +6,31 @@ import { EntityFilterValue as i, EntityFilterValueText as a } from "../filters/E
6
6
  import { DeferredFilterSearchInput as o } from "../filters/DeferredFilterSearchInput.js";
7
7
  import { BackofficeListToolbar as s } from "../lists/BackofficeListToolbar.js";
8
8
  import { BackofficeListFilterProvider as c } from "./BackofficeListFilterContext.js";
9
- import { useBackofficeInfiniteScrollSentinel as l } from "../../../hooks/useBackofficeInfiniteScrollSentinel.js";
10
- import { isDevEnv as u } from "../../../relay/envHelpers.js";
11
- import { controlsRow as ee, embeddedContainer as te, embeddedHeader as ne, filterInput as d } from "./backofficeEntityListScaffold.css.js";
12
- import { useCallback as f, useEffect as re, useMemo as p, useState as m } from "react";
9
+ import { BACKOFFICE_LIST_BODY_SCROLL_MODE as l } from "./backofficeListScrollMode.js";
10
+ import { useBackofficeInfiniteScrollSentinel as u } from "../../../hooks/useBackofficeInfiniteScrollSentinel.js";
11
+ import { isDevEnv as ee } from "../../../relay/envHelpers.js";
12
+ import { controlsRow as te, embeddedContainer as ne, embeddedHeader as re, filterInput as d, tableHost as ie } from "./backofficeEntityListScaffold.css.js";
13
+ import { useCallback as f, useEffect as ae, useMemo as p, useState as m } from "react";
13
14
  import { Fragment as h, jsx as g, jsxs as _ } from "react/jsx-runtime";
14
- import { useTranslation as ie } from "react-i18next";
15
+ import { useTranslation as oe } from "react-i18next";
15
16
  import { Button as v } from "@plumile/ui/atomic/atoms/button/Button.js";
16
17
  import { SimpleSelect as y } from "@plumile/ui/components/select/SimpleSelect.js";
17
- import { BackofficeEmptyState as b } from "@plumile/ui/backoffice/molecules/backoffice_empty_state/BackofficeEmptyState.js";
18
- import { InlineBanner as ae } from "@plumile/ui/backoffice/molecules/inline_banner/InlineBanner.js";
19
- import { BackofficePageHeader as oe } from "@plumile/ui/backoffice/molecules/backoffice_page_header/BackofficePageHeader.js";
20
- import { readWhereValue as x, setWhereValue as S } from "@plumile/backoffice-core/filters/where.js";
21
- import { BackofficeTableSkeleton as se } from "@plumile/ui/backoffice/molecules/backoffice_table_skeleton/BackofficeTableSkeleton.js";
22
- import { BackofficeFilterDrawer as ce } from "@plumile/ui/backoffice/molecules/backoffice_filter_drawer/BackofficeFilterDrawer.js";
23
- import { BackofficeFilterField as le } from "@plumile/ui/backoffice/molecules/backoffice_filter_field/BackofficeFilterField.js";
24
- import { BackofficeInfiniteListStatus as ue } from "@plumile/ui/backoffice/molecules/backoffice_infinite_list_status/BackofficeInfiniteListStatus.js";
25
- import { FilterChipRow as de } from "@plumile/ui/backoffice/molecules/filter_chip_row/FilterChipRow.js";
26
- import { BackofficeVirtualizedConnectionTable as fe } from "@plumile/ui/backoffice/organisms/backoffice_virtualized_connection_table/BackofficeVirtualizedConnectionTable.js";
27
- import { ListPageTemplate as pe } from "@plumile/ui/backoffice/templates/list_page_template/ListPageTemplate.js";
28
- import { ResponsiveRecordList as me } from "@plumile/ui/components/data-table/ResponsiveRecordList.js";
29
- import { denseTableClass as he } from "@plumile/ui/shared/backofficeTableDensity.css.js";
30
- import { resolveBackofficeListRuntimeConfig as ge } from "@plumile/backoffice-core/config/listRuntime.js";
18
+ import { BackofficeEmptyState as se } from "@plumile/ui/backoffice/molecules/backoffice_empty_state/BackofficeEmptyState.js";
19
+ import { InlineBanner as ce } from "@plumile/ui/backoffice/molecules/inline_banner/InlineBanner.js";
20
+ import { BackofficePageHeader as le } from "@plumile/ui/backoffice/molecules/backoffice_page_header/BackofficePageHeader.js";
21
+ import { readWhereValue as b, setWhereValue as x } from "@plumile/backoffice-core/filters/where.js";
22
+ import { BackofficeTableSkeleton as ue } from "@plumile/ui/backoffice/molecules/backoffice_table_skeleton/BackofficeTableSkeleton.js";
23
+ import { BackofficeFilterDrawer as de } from "@plumile/ui/backoffice/molecules/backoffice_filter_drawer/BackofficeFilterDrawer.js";
24
+ import { BackofficeFilterField as fe } from "@plumile/ui/backoffice/molecules/backoffice_filter_field/BackofficeFilterField.js";
25
+ import { BackofficeInfiniteListStatus as pe } from "@plumile/ui/backoffice/molecules/backoffice_infinite_list_status/BackofficeInfiniteListStatus.js";
26
+ import { FilterChipRow as me } from "@plumile/ui/backoffice/molecules/filter_chip_row/FilterChipRow.js";
27
+ import { BackofficeVirtualizedConnectionTable as he } from "@plumile/ui/backoffice/organisms/backoffice_virtualized_connection_table/BackofficeVirtualizedConnectionTable.js";
28
+ import { ListPageTemplate as ge } from "@plumile/ui/backoffice/templates/list_page_template/ListPageTemplate.js";
29
+ import { ResponsiveRecordList as _e } from "@plumile/ui/components/data-table/ResponsiveRecordList.js";
30
+ import { denseTableClass as S } from "@plumile/ui/shared/backofficeTableDensity.css.js";
31
+ import { resolveBackofficeListRuntimeConfig as ve } from "@plumile/backoffice-core/config/listRuntime.js";
31
32
  //#region src/components/backoffice/scaffolds/BackofficeEntityListScaffold.tsx
32
- var C = (e, t) => e(t), _e = (e, t) => e.fromGraphQL != null && t != null ? e.fromGraphQL(t) : x(t, e.whereKey ?? e.id, e.path), ve = (e, t, n) => {
33
+ var C = (e, t) => e(t), w = (e, t) => e.fromGraphQL != null && t != null ? e.fromGraphQL(t) : b(t, e.whereKey ?? e.id, e.path), ye = (e, t, n) => {
33
34
  if (t == null) return null;
34
35
  if (Array.isArray(t)) {
35
36
  let e = t.map((e) => {
@@ -46,21 +47,21 @@ var C = (e, t) => e(t), _e = (e, t) => e.fromGraphQL != null && t != null ? e.fr
46
47
  entityId: e.entity,
47
48
  id: r
48
49
  }) : e.kind === "enum" ? n.enumLabel(r) : r;
49
- }, ye = (e) => {
50
+ }, be = (e) => {
50
51
  let t = new Date(e);
51
52
  if (Number.isNaN(t.getTime())) return e;
52
53
  let n = t.getTimezoneOffset() * 6e4;
53
54
  return new Date(t.getTime() - n).toISOString().slice(0, 16);
54
- }, be = (e) => {
55
+ }, xe = (e) => {
55
56
  let t = e.trim();
56
57
  if (t === "") return "";
57
58
  let n = new Date(t);
58
59
  return Number.isNaN(n.getTime()) ? t : n.toISOString();
59
- }, w = (i) => {
60
- let { t: x } = ie(), { t: w } = e(), { config: T, state: E, pushState: D, rows: O, getRowId: k, columns: A, gridTemplateColumns: j, hasNextPage: M, isLoadingMore: N, isRefreshing: xe = !1, onLoadMore: P, onRefresh: F, totalCount: I, emptyState: L, statusBanner: R, header: Se, headerActions: Ce, isLoadingInitial: we = !1, variant: Te = "page", showFilters: Ee = !0 } = i, z = T.list, De = T.listDefaults ?? z.defaultState ?? {
60
+ }, T = (i) => {
61
+ let { t: b } = oe(), { t: T } = e(), { config: E, state: D, pushState: O, rows: k, getRowId: A, columns: j, gridTemplateColumns: M, hasNextPage: N, isLoadingMore: P, isRefreshing: Se = !1, onLoadMore: F, onRefresh: I, totalCount: L, emptyState: R, statusBanner: z, header: B, headerActions: Ce, isLoadingInitial: we = !1, variant: Te = "page", showFilters: Ee = !0 } = i, V = E.list, De = E.listDefaults ?? V.defaultState ?? {
61
62
  where: null,
62
63
  sort: null
63
- }, B = p(() => A.some((e) => e.isPrimary === !0) || A.length === 0 ? A : A.map((e, t) => {
64
+ }, H = p(() => j.some((e) => e.isPrimary === !0) || j.length === 0 ? j : j.map((e, t) => {
64
65
  let { header: n } = e;
65
66
  return t === 0 ? {
66
67
  ...e,
@@ -70,32 +71,32 @@ var C = (e, t) => e(t), _e = (e, t) => e.fromGraphQL != null && t != null ? e.fr
70
71
  ...e,
71
72
  header: n
72
73
  };
73
- }), [A]), V = p(() => {
74
+ }), [j]), U = p(() => {
74
75
  let e = [];
75
- for (let t of z.filters) {
76
- let n = _e(t, E.where), r = ve(t, n, {
76
+ for (let t of V.filters) {
77
+ let n = w(t, D.where), r = ye(t, n, {
77
78
  enumLabel: (e) => {
78
79
  if (t.kind !== "enum") return e;
79
80
  let n = t.options.find((t) => t.value === e);
80
- return n == null ? e : C(n.label, x);
81
+ return n == null ? e : C(n.label, b);
81
82
  },
82
83
  booleanLabel: (e) => {
83
84
  if (t.kind === "boolean") {
84
- if (e && t.trueLabel != null) return C(t.trueLabel, x);
85
- if (!e && t.falseLabel != null) return C(t.falseLabel, x);
85
+ if (e && t.trueLabel != null) return C(t.trueLabel, b);
86
+ if (!e && t.falseLabel != null) return C(t.falseLabel, b);
86
87
  }
87
- return w(e ? "filters.boolean.yes" : "filters.boolean.no");
88
+ return T(e ? "filters.boolean.yes" : "filters.boolean.no");
88
89
  },
89
90
  fallbackBooleanLabels: {
90
- yes: w("filters.boolean.yes"),
91
- no: w("filters.boolean.no")
91
+ yes: T("filters.boolean.yes"),
92
+ no: T("filters.boolean.no")
92
93
  }
93
94
  });
94
95
  if (r != null) {
95
96
  let i = String(n);
96
97
  Array.isArray(n) && (i = n.join(","));
97
98
  let a = /* @__PURE__ */ _("span", { children: [
98
- C(t.label, x),
99
+ C(t.label, b),
99
100
  ": ",
100
101
  r
101
102
  ] });
@@ -103,9 +104,9 @@ var C = (e, t) => e(t), _e = (e, t) => e.fromGraphQL != null && t != null ? e.fr
103
104
  id: `${t.id}:${i}`,
104
105
  label: a,
105
106
  onRemove: () => {
106
- let e = t.whereKey ?? t.id, n = S(E.where, e, null, t.path);
107
- D({
108
- ...E,
107
+ let e = t.whereKey ?? t.id, n = x(D.where, e, null, t.path);
108
+ O({
109
+ ...D,
109
110
  where: n
110
111
  });
111
112
  }
@@ -114,25 +115,25 @@ var C = (e, t) => e(t), _e = (e, t) => e.fromGraphQL != null && t != null ? e.fr
114
115
  }
115
116
  return e;
116
117
  }, [
117
- z.filters,
118
+ V.filters,
119
+ O,
118
120
  D,
119
- E,
120
- w,
121
- x
122
- ]), H = f(() => {
123
- D({ ...De });
124
- }, [De, D]), [Oe, ke] = m(!1), [U, Ae] = m(""), [W, je] = m(null), G = f((e) => {
125
- let n = e.whereKey ?? e.id, r = _e(e, E.where), i = "";
121
+ T,
122
+ b
123
+ ]), W = f(() => {
124
+ O({ ...De });
125
+ }, [De, O]), [Oe, ke] = m(!1), [G, Ae] = m(""), [K, je] = m(null), q = f((e) => {
126
+ let n = e.whereKey ?? e.id, r = w(e, D.where), i = "";
126
127
  typeof r == "string" && (i = r), typeof r == "number" && Number.isFinite(r) && (i = String(r));
127
- let s = C(e.label, x);
128
+ let s = C(e.label, b);
128
129
  if (e.kind === "text") {
129
- let t = w("filters.placeholders.search", { label: e.placeholderLabel == null ? s : C(e.placeholderLabel, x) });
130
- return e.placeholderText != null && (t = C(e.placeholderText, x)), /* @__PURE__ */ g(o, {
131
- value: ye(i),
130
+ let t = T("filters.placeholders.search", { label: e.placeholderLabel == null ? s : C(e.placeholderLabel, b) });
131
+ return e.placeholderText != null && (t = C(e.placeholderText, b)), /* @__PURE__ */ g(o, {
132
+ value: be(i),
132
133
  onApply: (t) => {
133
- let r = be(t), i = S(E.where, n, r, e.path);
134
- D({
135
- ...E,
134
+ let r = xe(t), i = x(D.where, n, r, e.path);
135
+ O({
136
+ ...D,
136
137
  where: i
137
138
  });
138
139
  },
@@ -142,13 +143,13 @@ var C = (e, t) => e(t), _e = (e, t) => e.fromGraphQL != null && t != null ? e.fr
142
143
  });
143
144
  }
144
145
  if (e.kind === "datetime") {
145
- let t = w("filters.placeholders.search", { label: e.placeholderLabel == null ? s : C(e.placeholderLabel, x) });
146
- return e.placeholderText != null && (t = C(e.placeholderText, x)), /* @__PURE__ */ g(o, {
146
+ let t = T("filters.placeholders.search", { label: e.placeholderLabel == null ? s : C(e.placeholderLabel, b) });
147
+ return e.placeholderText != null && (t = C(e.placeholderText, b)), /* @__PURE__ */ g(o, {
147
148
  value: i,
148
149
  onApply: (t) => {
149
- let r = S(E.where, n, t, e.path);
150
- D({
151
- ...E,
150
+ let r = x(D.where, n, t, e.path);
151
+ O({
152
+ ...D,
152
153
  where: r
153
154
  });
154
155
  },
@@ -159,13 +160,13 @@ var C = (e, t) => e(t), _e = (e, t) => e.fromGraphQL != null && t != null ? e.fr
159
160
  });
160
161
  }
161
162
  if (e.kind === "number") {
162
- let t = w("filters.placeholders.search", { label: e.placeholderLabel == null ? s : C(e.placeholderLabel, x) });
163
- return e.placeholderText != null && (t = C(e.placeholderText, x)), /* @__PURE__ */ g(o, {
163
+ let t = T("filters.placeholders.search", { label: e.placeholderLabel == null ? s : C(e.placeholderLabel, b) });
164
+ return e.placeholderText != null && (t = C(e.placeholderText, b)), /* @__PURE__ */ g(o, {
164
165
  value: i,
165
166
  onApply: (t) => {
166
- let r = t.trim(), i = r === "" ? null : Number(r), a = S(E.where, n, Number.isFinite(i) ? i : null, e.path);
167
- D({
168
- ...E,
167
+ let r = t.trim(), i = r === "" ? null : Number(r), a = x(D.where, n, Number.isFinite(i) ? i : null, e.path);
168
+ O({
169
+ ...D,
169
170
  where: a
170
171
  });
171
172
  },
@@ -180,19 +181,19 @@ var C = (e, t) => e(t), _e = (e, t) => e.fromGraphQL != null && t != null ? e.fr
180
181
  options: [{
181
182
  id: "any",
182
183
  value: "",
183
- label: w("filters.all", { label: s })
184
+ label: T("filters.all", { label: s })
184
185
  }, ...e.options.map((e) => ({
185
186
  id: e.value,
186
187
  value: e.value,
187
- label: C(e.label, x)
188
+ label: C(e.label, b)
188
189
  }))],
189
190
  value: i,
190
191
  size: "small",
191
192
  ariaLabel: s,
192
193
  onChange: (t) => {
193
- let r = S(E.where, n, t, e.path);
194
- D({
195
- ...E,
194
+ let r = x(D.where, n, t, e.path);
195
+ O({
196
+ ...D,
196
197
  where: r
197
198
  });
198
199
  }
@@ -202,13 +203,13 @@ var C = (e, t) => e(t), _e = (e, t) => e.fromGraphQL != null && t != null ? e.fr
202
203
  typeof r == "boolean" && (t = r);
203
204
  let i = "";
204
205
  t === !0 && (i = "true"), t === !1 && (i = "false");
205
- let a = e.trueLabel == null ? w("filters.boolean.yes") : C(e.trueLabel, x), o = e.falseLabel == null ? w("filters.boolean.no") : C(e.falseLabel, x);
206
+ let a = e.trueLabel == null ? T("filters.boolean.yes") : C(e.trueLabel, b), o = e.falseLabel == null ? T("filters.boolean.no") : C(e.falseLabel, b);
206
207
  return /* @__PURE__ */ g(y, {
207
208
  options: [
208
209
  {
209
210
  id: "any",
210
211
  value: "",
211
- label: w("filters.all", { label: s })
212
+ label: T("filters.all", { label: s })
212
213
  },
213
214
  {
214
215
  id: "true",
@@ -227,16 +228,16 @@ var C = (e, t) => e(t), _e = (e, t) => e.fromGraphQL != null && t != null ? e.fr
227
228
  onChange: (t) => {
228
229
  let r = null;
229
230
  t === "true" && (r = !0), t === "false" && (r = !1);
230
- let i = S(E.where, n, r, e.path);
231
- D({
232
- ...E,
231
+ let i = x(D.where, n, r, e.path);
232
+ O({
233
+ ...D,
233
234
  where: i
234
235
  });
235
236
  }
236
237
  });
237
238
  }
238
239
  let c = (() => {
239
- if (e.pickerScope != null) return typeof e.pickerScope == "function" ? e.pickerScope(E.where) : e.pickerScope;
240
+ if (e.pickerScope != null) return typeof e.pickerScope == "function" ? e.pickerScope(D.where) : e.pickerScope;
240
241
  })(), l = null;
241
242
  typeof r == "string" && (l = r);
242
243
  let u = (r = null, i = !1) => {
@@ -246,7 +247,7 @@ var C = (e, t) => e(t), _e = (e, t) => e.fromGraphQL != null && t != null ? e.fr
246
247
  value: l,
247
248
  displayValue: a,
248
249
  isResolving: i,
249
- placeholder: w("filters.placeholders.anyEntity", { label: s }),
250
+ placeholder: T("filters.placeholders.anyEntity", { label: s }),
250
251
  onPick: () => {
251
252
  je({
252
253
  entity: e.entity,
@@ -257,9 +258,9 @@ var C = (e, t) => e(t), _e = (e, t) => e.fromGraphQL != null && t != null ? e.fr
257
258
  });
258
259
  },
259
260
  onClear: () => {
260
- let t = S(E.where, n, null, e.path);
261
- D({
262
- ...E,
261
+ let t = x(D.where, n, null, e.path);
262
+ O({
263
+ ...D,
263
264
  where: t
264
265
  });
265
266
  }
@@ -270,88 +271,88 @@ var C = (e, t) => e(t), _e = (e, t) => e.fromGraphQL != null && t != null ? e.fr
270
271
  id: l,
271
272
  children: (e, t) => {
272
273
  let n = t?.status === "loading";
273
- return u(n ? w("common.loading") : e, n);
274
+ return u(n ? T("common.loading") : e, n);
274
275
  }
275
276
  });
276
277
  }, [
278
+ O,
277
279
  D,
278
- E,
279
- w,
280
- x
281
- ]), Me = p(() => z.filters.some((e) => e.placement != null), [z.filters]), K = p(() => {
282
- if (z.filters.length === 0) return [];
283
- let e = z.ui?.toolbar?.maxPromotedFilters ?? 3;
284
- return Me ? z.filters.filter((e) => e.placement === "quick" || e.placement === "both") : z.filters.slice(0, e);
280
+ T,
281
+ b
282
+ ]), Me = p(() => V.filters.some((e) => e.placement != null), [V.filters]), J = p(() => {
283
+ if (V.filters.length === 0) return [];
284
+ let e = V.ui?.toolbar?.maxPromotedFilters ?? 3;
285
+ return Me ? V.filters.filter((e) => e.placement === "quick" || e.placement === "both") : V.filters.slice(0, e);
285
286
  }, [
286
- z.filters,
287
- z.ui?.toolbar,
287
+ V.filters,
288
+ V.ui?.toolbar,
288
289
  Me
289
- ]), q = p(() => z.filters.filter((e) => e.placement == null ? !0 : e.placement === "drawer" || e.placement === "both"), [z.filters]), J = p(() => K.find((e) => e.kind === "text"), [K]), Ne = p(() => {
290
- let e = K.filter((e) => e !== J);
290
+ ]), Y = p(() => V.filters.filter((e) => e.placement == null ? !0 : e.placement === "drawer" || e.placement === "both"), [V.filters]), X = p(() => J.find((e) => e.kind === "text"), [J]), Ne = p(() => {
291
+ let e = J.filter((e) => e !== X);
291
292
  return e.length === 0 ? null : /* @__PURE__ */ g("div", {
292
- className: ee,
293
- children: e.map((e) => /* @__PURE__ */ g("span", { children: G(e) }, e.id))
293
+ className: te,
294
+ children: e.map((e) => /* @__PURE__ */ g("span", { children: q(e) }, e.id))
294
295
  });
295
296
  }, [
296
- K,
297
- G,
298
- J
299
- ]), Pe = p(() => J == null ? null : G(J), [G, J]), Fe = p(() => {
300
- if (z.sorts.length === 0) return null;
301
- let e = z.sorts[0];
297
+ J,
298
+ q,
299
+ X
300
+ ]), Pe = p(() => X == null ? null : q(X), [q, X]), Fe = p(() => {
301
+ if (V.sorts.length === 0) return null;
302
+ let e = V.sorts[0];
302
303
  return e == null ? null : /* @__PURE__ */ g(y, {
303
- options: z.sorts.map((e) => ({
304
+ options: V.sorts.map((e) => ({
304
305
  id: e.id,
305
306
  value: e.id,
306
- label: C(e.label, x)
307
+ label: C(e.label, b)
307
308
  })),
308
- value: E.sort ?? e.id,
309
+ value: D.sort ?? e.id,
309
310
  size: "small",
310
- ariaLabel: w("list.sort.label"),
311
+ ariaLabel: T("list.sort.label"),
311
312
  onChange: (e) => {
312
- D({
313
- ...E,
313
+ O({
314
+ ...D,
314
315
  sort: e
315
316
  });
316
317
  }
317
318
  });
318
319
  }, [
319
- z.sorts,
320
+ V.sorts,
321
+ O,
320
322
  D,
321
- E,
322
- w,
323
- x
324
- ]), Ie = p(() => V.length === 0 ? null : /* @__PURE__ */ g(de, {
325
- chips: V,
326
- onClearAll: H
327
- }), [V, H]), Le = p(() => {
328
- if (q.length === 0) return [];
329
- let e = U.trim().toLowerCase(), t = [];
330
- for (let n of q) {
331
- let r = C(n.label, x);
323
+ T,
324
+ b
325
+ ]), Ie = p(() => U.length === 0 ? null : /* @__PURE__ */ g(me, {
326
+ chips: U,
327
+ onClearAll: W
328
+ }), [U, W]), Le = p(() => {
329
+ if (Y.length === 0) return [];
330
+ let e = G.trim().toLowerCase(), t = [];
331
+ for (let n of Y) {
332
+ let r = C(n.label, b);
332
333
  (e === "" || r.toLowerCase().includes(e)) && t.push({
333
334
  id: n.id,
334
- node: /* @__PURE__ */ g(le, {
335
+ node: /* @__PURE__ */ g(fe, {
335
336
  label: r,
336
- children: G(n)
337
+ children: q(n)
337
338
  })
338
339
  });
339
340
  }
340
341
  return t.length === 0 ? [] : [{
341
342
  id: "backoffice.filters.sections.default",
342
- title: w("filters.sections.default"),
343
+ title: T("filters.sections.default"),
343
344
  items: t
344
345
  }];
345
346
  }, [
346
- q,
347
- U,
347
+ Y,
348
348
  G,
349
- w,
350
- x
349
+ q,
350
+ T,
351
+ b
351
352
  ]), Re = p(() => {
352
- if (q.length === 0) return null;
353
- let e = V.length, t = w("filters.trigger");
354
- return e > 0 && (t = w("filters.triggerWithCount", { count: e })), /* @__PURE__ */ g(v, {
353
+ if (Y.length === 0) return null;
354
+ let e = U.length, t = T("filters.trigger");
355
+ return e > 0 && (t = T("filters.triggerWithCount", { count: e })), /* @__PURE__ */ g(v, {
355
356
  type: "button",
356
357
  variant: "secondary",
357
358
  size: "small",
@@ -361,209 +362,216 @@ var C = (e, t) => e(t), _e = (e, t) => e.fromGraphQL != null && t != null ? e.fr
361
362
  children: t
362
363
  });
363
364
  }, [
364
- V.length,
365
- q.length,
366
- w
367
- ]), ze = /* @__PURE__ */ g(ce, {
365
+ U.length,
366
+ Y.length,
367
+ T
368
+ ]), ze = /* @__PURE__ */ g(de, {
368
369
  isOpen: Oe,
369
370
  onClose: () => {
370
371
  ke(!1), Ae("");
371
372
  },
372
373
  sections: Le,
373
- searchValue: U,
374
+ searchValue: G,
374
375
  onSearchChange: (e) => {
375
376
  Ae(e);
376
377
  },
377
- onReset: H,
378
- emptyLabel: U.trim() === "" ? void 0 : w("filters.drawer.emptySearchResults")
379
- }), Be = p(() => L ?? (we ? /* @__PURE__ */ g(se, {
378
+ onReset: W,
379
+ emptyLabel: G.trim() === "" ? void 0 : T("filters.drawer.emptySearchResults")
380
+ }), Be = p(() => R ?? (we ? /* @__PURE__ */ g(ue, {
380
381
  variant: "embedded",
381
- ariaLabel: w("common.loading")
382
- }) : V.length > 0 ? /* @__PURE__ */ g(b, {
383
- title: w("emptyState.listEmpty.title"),
384
- description: w("emptyState.listEmptyFiltered.description"),
382
+ ariaLabel: T("common.loading")
383
+ }) : U.length > 0 ? /* @__PURE__ */ g(se, {
384
+ title: T("emptyState.listEmpty.title"),
385
+ description: T("emptyState.listEmptyFiltered.description"),
385
386
  actions: /* @__PURE__ */ g(v, {
386
387
  type: "button",
387
388
  variant: "secondary",
388
389
  size: "small",
389
- onClick: H,
390
- children: w("emptyState.listEmptyFiltered.actions.reset")
390
+ onClick: W,
391
+ children: T("emptyState.listEmptyFiltered.actions.reset")
391
392
  })
392
- }) : /* @__PURE__ */ g(b, {
393
- title: w("emptyState.listEmpty.title"),
394
- description: w("emptyState.listEmpty.description")
393
+ }) : /* @__PURE__ */ g(se, {
394
+ title: T("emptyState.listEmpty.title"),
395
+ description: T("emptyState.listEmpty.description")
395
396
  })), [
396
- V.length,
397
- L,
398
- H,
397
+ U.length,
398
+ R,
399
+ W,
399
400
  we,
400
- w
401
- ]), Ve = p(() => typeof I == "number" ? /* @__PURE__ */ g("span", { children: w("list.showing", {
402
- shown: O.length,
403
- total: I
404
- }) }) : O.length === 0 ? null : /* @__PURE__ */ g("span", { children: w("list.loaded", { count: O.length }) }), [
405
- O.length,
406
- w,
407
- I
408
- ]), Y = p(() => {
409
- let e = z.ui?.displayMode ?? z.responsive?.mode ?? "auto";
410
- return ge({
411
- kind: z.kind,
401
+ T
402
+ ]), Ve = p(() => typeof L == "number" ? /* @__PURE__ */ g("span", { children: T("list.showing", {
403
+ shown: k.length,
404
+ total: L
405
+ }) }) : k.length === 0 ? null : /* @__PURE__ */ g("span", { children: T("list.loaded", { count: k.length }) }), [
406
+ k.length,
407
+ T,
408
+ L
409
+ ]), Z = p(() => {
410
+ let e = V.ui?.displayMode ?? V.responsive?.mode ?? "auto";
411
+ return ve({
412
+ kind: V.kind,
412
413
  displayMode: e,
413
- ui: z.ui
414
+ ui: V.ui
414
415
  });
415
416
  }, [
416
- z.kind,
417
- z.responsive?.mode,
418
- z.ui
419
- ]), X = typeof I == "number" && O.length < I && !M;
420
- re(() => {
421
- !X || !Y.infiniteScroll.showInconsistentPageInfo || !u() || console.warn("Backoffice list received inconsistent pageInfo: loaded rows are lower than totalCount but hasNextPage is false.", {
422
- entityId: T.id,
423
- loadedCount: O.length,
424
- totalCount: I
417
+ V.kind,
418
+ V.responsive?.mode,
419
+ V.ui
420
+ ]), Q = typeof L == "number" && k.length < L && !N;
421
+ ae(() => {
422
+ !Q || !Z.infiniteScroll.showInconsistentPageInfo || !ee() || console.warn("Backoffice list received inconsistent pageInfo: loaded rows are lower than totalCount but hasNextPage is false.", {
423
+ entityId: E.id,
424
+ loadedCount: k.length,
425
+ totalCount: L
425
426
  });
426
427
  }, [
427
- T.id,
428
- X,
429
- O.length,
430
- Y.infiniteScroll.showInconsistentPageInfo,
431
- I
428
+ E.id,
429
+ Q,
430
+ k.length,
431
+ Z.infiniteScroll.showInconsistentPageInfo,
432
+ L
432
433
  ]);
433
- let Z = i.virtualize === !0 || Y.virtualization.enabled, { sentinelRef: He } = l({
434
- enabled: !Z && Y.infiniteScroll.enabled,
435
- hasNextPage: M,
436
- isLoading: N,
437
- onIntersect: P,
438
- rootMargin: Y.infiniteScroll.rootMargin,
439
- threshold: Y.infiniteScroll.threshold
440
- }), Q = Se?.title ?? C(z.title, x), Ue = Se?.subtitle, We = B.find((e) => e.mobileRole === "action" || e.id === "actions"), Ge = z.ui?.displayMode ?? z.responsive?.mode ?? "auto", Ke = z.ui?.density ?? z.responsive?.density ?? "compact", qe = /* @__PURE__ */ g(n, {
434
+ let He = i.virtualize === !0 || Z.virtualization.enabled, { sentinelRef: Ue } = u({
435
+ enabled: !He && Z.infiniteScroll.enabled,
436
+ hasNextPage: N,
437
+ isLoading: P,
438
+ onIntersect: F,
439
+ rootMargin: Z.infiniteScroll.rootMargin,
440
+ threshold: Z.infiniteScroll.threshold
441
+ }), We = B?.title ?? C(V.title, b), Ge = B?.subtitle, Ke = H.find((e) => e.mobileRole === "action" || e.id === "actions"), qe = V.ui?.displayMode ?? V.responsive?.mode ?? "auto", Je = V.ui?.density ?? V.responsive?.density ?? "compact", Ye = /* @__PURE__ */ g(n, {
441
442
  fallback: (e) => {
442
443
  let { reset: t } = e;
443
- return /* @__PURE__ */ g(ae, {
444
+ return /* @__PURE__ */ g(ce, {
444
445
  tone: "danger",
445
- title: w("list.errors.title"),
446
+ title: T("list.errors.title"),
446
447
  actions: /* @__PURE__ */ g(v, {
447
448
  type: "button",
448
449
  variant: "secondary",
449
450
  size: "small",
450
451
  onClick: () => {
451
- t(), F?.();
452
+ t(), I?.();
452
453
  },
453
- children: w("list.actions.retry")
454
+ children: T("list.actions.retry")
454
455
  }),
455
- children: w("list.errors.tableFailed")
456
+ children: T("list.errors.tableFailed")
456
457
  });
457
458
  },
458
- children: Z ? /* @__PURE__ */ g(fe, {
459
- columns: B,
460
- rows: O,
461
- getRowId: k,
459
+ children: He ? /* @__PURE__ */ g(he, {
460
+ columns: H,
461
+ rows: k,
462
+ getRowId: A,
462
463
  emptyState: Be,
463
- className: he,
464
- gridTemplateColumns: j,
465
- virtualization: Y.virtualization,
464
+ className: S,
465
+ gridTemplateColumns: M,
466
+ virtualization: Z.virtualization,
466
467
  infiniteScroll: {
467
- enabled: Y.infiniteScroll.enabled,
468
- thresholdPx: Y.infiniteScroll.thresholdPx,
469
- autoLoad: Y.infiniteScroll.autoLoad
468
+ enabled: Z.infiniteScroll.enabled,
469
+ thresholdPx: Z.infiniteScroll.thresholdPx,
470
+ autoLoad: Z.infiniteScroll.autoLoad
470
471
  },
471
- hasNextPage: M,
472
- isLoadingMore: N,
473
- onLoadMore: P
474
- }) : /* @__PURE__ */ g(me, {
475
- columns: B,
476
- rows: O,
477
- getRowId: k,
472
+ hasNextPage: N,
473
+ isLoadingMore: P,
474
+ onLoadMore: F,
475
+ bodyScrollMode: l
476
+ }) : /* @__PURE__ */ g(_e, {
477
+ columns: H,
478
+ rows: k,
479
+ getRowId: A,
478
480
  emptyState: Be,
479
- className: he,
480
- gridTemplateColumns: j,
481
- mode: Ge,
482
- density: Ke,
483
- renderAction: (e) => We?.cell(e) ?? null
481
+ className: S,
482
+ gridTemplateColumns: M,
483
+ mode: qe,
484
+ density: Je,
485
+ bodyScrollMode: l,
486
+ bodyFooterNode: Z.infiniteScroll.enabled ? /* @__PURE__ */ g("div", {
487
+ ref: Ue,
488
+ "aria-hidden": "true"
489
+ }) : null,
490
+ renderAction: (e) => Ke?.cell(e) ?? null
484
491
  })
485
- }), Je = Ee ? /* @__PURE__ */ _(h, { children: [/* @__PURE__ */ g(s, {
492
+ }), Xe = Ee ? /* @__PURE__ */ _(h, { children: [/* @__PURE__ */ g(s, {
486
493
  primaryFilters: Pe != null || Ne != null ? /* @__PURE__ */ _(h, { children: [Pe, Ne] }) : null,
487
494
  filterDrawerTrigger: Re,
488
495
  sortControl: Fe,
489
- utilityActions: F == null ? null : /* @__PURE__ */ g(v, {
496
+ utilityActions: I == null ? null : /* @__PURE__ */ g(v, {
490
497
  type: "button",
491
498
  variant: "secondary",
492
499
  size: "small",
493
- isLoading: xe,
494
- loadingLabel: w("list.actions.refreshing"),
500
+ isLoading: Se,
501
+ loadingLabel: T("list.actions.refreshing"),
495
502
  onClick: () => {
496
- F();
503
+ I();
497
504
  },
498
- children: w("list.actions.refresh")
505
+ children: T("list.actions.refresh")
499
506
  }),
500
507
  activeFilters: Ie,
501
508
  density: "compact"
502
- }), ze] }) : null, Ye = /* @__PURE__ */ _("div", { children: [qe, /* @__PURE__ */ g(r, {
503
- isOpen: W != null,
504
- entity: W?.entity ?? T.id,
505
- title: W?.label ?? w("picker.title"),
506
- scope: W?.scope,
507
- onClose: () => {
508
- je(null);
509
- },
510
- onSelectId: (e) => {
511
- if (W == null) return;
512
- let t = S(E.where, W.whereKey, e, W.path);
513
- D({
514
- ...E,
515
- where: t
516
- });
517
- }
518
- })] }), $ = O.length > 0 || N || M ? /* @__PURE__ */ _(h, { children: [!Z && /* @__PURE__ */ g("div", {
519
- ref: He,
520
- "aria-hidden": "true"
521
- }), /* @__PURE__ */ g(ue, {
522
- loadedCount: O.length,
523
- totalCount: I,
524
- hasNextPage: M,
525
- isLoading: N,
526
- pageInfoState: X ? "inconsistent" : N ? "loading" : M ? "ready" : "complete",
509
+ }), ze] }) : null, Ze = /* @__PURE__ */ _("div", {
510
+ className: ie,
511
+ children: [Ye, /* @__PURE__ */ g(r, {
512
+ isOpen: K != null,
513
+ entity: K?.entity ?? E.id,
514
+ title: K?.label ?? T("picker.title"),
515
+ scope: K?.scope,
516
+ onClose: () => {
517
+ je(null);
518
+ },
519
+ onSelectId: (e) => {
520
+ if (K == null) return;
521
+ let t = x(D.where, K.whereKey, e, K.path);
522
+ O({
523
+ ...D,
524
+ where: t
525
+ });
526
+ }
527
+ })]
528
+ }), $ = k.length > 0 || P || N ? /* @__PURE__ */ g(h, { children: /* @__PURE__ */ g(pe, {
529
+ loadedCount: k.length,
530
+ totalCount: L,
531
+ hasNextPage: N,
532
+ isLoading: P,
533
+ pageInfoState: Q ? "inconsistent" : P ? "loading" : N ? "ready" : "complete",
527
534
  loadedLabel: Ve,
528
- loadingLabel: w("list.loadMore.loading"),
529
- endLabel: w("list.loadMore.end")
530
- })] }) : null;
535
+ loadingLabel: T("list.loadMore.loading"),
536
+ endLabel: T("list.loadMore.end")
537
+ }) }) : null;
531
538
  return Te === "embedded" ? /* @__PURE__ */ g(c, {
532
- config: T,
533
- state: E,
534
- pushState: D,
539
+ config: E,
540
+ state: D,
541
+ pushState: O,
535
542
  children: /* @__PURE__ */ _("div", {
536
- className: te,
543
+ className: ne,
537
544
  children: [
538
545
  /* @__PURE__ */ g("div", {
539
- className: ne,
540
- children: Q
546
+ className: re,
547
+ children: We
541
548
  }),
542
- Je,
543
- R,
544
- Ye,
549
+ Xe,
550
+ z,
551
+ Ze,
545
552
  $
546
553
  ]
547
554
  })
548
555
  }) : /* @__PURE__ */ g(c, {
549
- config: T,
550
- state: E,
551
- pushState: D,
552
- children: /* @__PURE__ */ g(pe, {
553
- headerNode: /* @__PURE__ */ g(oe, {
554
- title: Q,
555
- subtitle: Ue,
556
+ config: E,
557
+ state: D,
558
+ pushState: O,
559
+ children: /* @__PURE__ */ g(ge, {
560
+ headerNode: /* @__PURE__ */ g(le, {
561
+ title: We,
562
+ subtitle: Ge,
556
563
  actions: Ce
557
564
  }),
558
- toolbarNode: Je,
559
- statusNode: R,
560
- tableNode: Ye,
565
+ toolbarNode: Xe,
566
+ statusNode: z,
567
+ tableNode: Ze,
561
568
  tableFooterNode: $,
562
- presentation: "flat"
569
+ presentation: "flat",
570
+ bodyScrollMode: l
563
571
  })
564
572
  });
565
573
  };
566
574
  //#endregion
567
- export { w as BackofficeEntityListScaffold, w as default };
575
+ export { T as BackofficeEntityListScaffold, T as default };
568
576
 
569
577
  //# sourceMappingURL=BackofficeEntityListScaffold.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"BackofficeEntityListScaffold.js","names":[],"sources":["../../../../../src/components/backoffice/scaffolds/BackofficeEntityListScaffold.tsx"],"sourcesContent":["/* eslint-disable no-ternary */\nimport {\n type JSX,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport type { TFunction } from 'i18next';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@plumile/ui/atomic/atoms/button/Button.js';\nimport { BackofficeEmptyState } from '@plumile/ui/backoffice/molecules/backoffice_empty_state/BackofficeEmptyState.js';\nimport { BackofficeFilterDrawer } from '@plumile/ui/backoffice/molecules/backoffice_filter_drawer/BackofficeFilterDrawer.js';\nimport { BackofficeFilterField } from '@plumile/ui/backoffice/molecules/backoffice_filter_field/BackofficeFilterField.js';\nimport { BackofficeInfiniteListStatus } from '@plumile/ui/backoffice/molecules/backoffice_infinite_list_status/BackofficeInfiniteListStatus.js';\nimport { BackofficePageHeader } from '@plumile/ui/backoffice/molecules/backoffice_page_header/BackofficePageHeader.js';\nimport { BackofficeTableSkeleton } from '@plumile/ui/backoffice/molecules/backoffice_table_skeleton/BackofficeTableSkeleton.js';\nimport {\n FilterChipRow,\n type FilterChip,\n} from '@plumile/ui/backoffice/molecules/filter_chip_row/FilterChipRow.js';\nimport { InlineBanner } from '@plumile/ui/backoffice/molecules/inline_banner/InlineBanner.js';\nimport { BackofficeVirtualizedConnectionTable } from '@plumile/ui/backoffice/organisms/backoffice_virtualized_connection_table/BackofficeVirtualizedConnectionTable.js';\nimport { ListPageTemplate } from '@plumile/ui/backoffice/templates/list_page_template/ListPageTemplate.js';\nimport {\n type DataTableColumn,\n type GetRowId,\n} from '@plumile/ui/components/data-table/DataTable.js';\nimport { ResponsiveRecordList } from '@plumile/ui/components/data-table/ResponsiveRecordList.js';\nimport { SimpleSelect } from '@plumile/ui/components/select/SimpleSelect.js';\nimport { denseTableClass } from '@plumile/ui/shared/backofficeTableDensity.css.js';\n\nimport {\n readWhereValue,\n setWhereValue,\n} from '@plumile/backoffice-core/filters/where.js';\nimport { resolveBackofficeListRuntimeConfig } from '@plumile/backoffice-core/config/listRuntime.js';\nimport type {\n BackofficeFilterSpec,\n BackofficeListState,\n BackofficePickerScope,\n BackofficeRuntimeResolvedListFacetConfig,\n I18nLabel,\n} from '@plumile/backoffice-core/types.js';\n\nimport { BackofficeErrorBoundary } from '../errors/BackofficeErrorBoundary.js';\nimport {\n EntityFilterValue,\n EntityFilterValueText,\n} from '../filters/EntityFilterValue.js';\nimport { EntityIdPickerDialog } from '../pickers/EntityIdPickerDialog.js';\nimport { EntityIdFilterField } from '../filters/EntityIdFilterField.js';\nimport { DeferredFilterSearchInput } from '../filters/DeferredFilterSearchInput.js';\nimport { BackofficeListToolbar } from '../lists/BackofficeListToolbar.js';\nimport { BackofficeListFilterProvider } from './BackofficeListFilterContext.js';\nimport { useBackofficeReactTranslation } from '../../../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeInfiniteScrollSentinel } from '../../../hooks/useBackofficeInfiniteScrollSentinel.js';\nimport { isDevEnv } from '../../../relay/envHelpers.js';\n\nimport * as styles from './backofficeEntityListScaffold.css.js';\n\nconst resolveLabel = (label: I18nLabel, tApp: TFunction): string => {\n return label(tApp);\n};\n\nconst getFilterValue = <Where extends Record<string, unknown>>(\n filter: BackofficeFilterSpec<Where>,\n where: Where | null,\n): unknown => {\n if (filter.fromGraphQL != null && where != null) {\n return filter.fromGraphQL(where);\n }\n\n const key = (filter.whereKey ?? filter.id) as keyof Where;\n return readWhereValue(where, key, filter.path);\n};\n\nconst getFilterDisplayValue = <Where extends Record<string, unknown>>(\n filter: BackofficeFilterSpec<Where>,\n raw: unknown,\n options: {\n enumLabel: (value: string) => string;\n booleanLabel: (value: boolean) => string;\n fallbackBooleanLabels: { yes: string; no: string };\n },\n): ReactNode | null => {\n if (raw == null) {\n return null;\n }\n\n if (Array.isArray(raw)) {\n const normalized = raw\n .map((entry) => {\n if (entry == null) {\n return null;\n }\n if (\n typeof entry !== 'string' &&\n typeof entry !== 'number' &&\n typeof entry !== 'boolean'\n ) {\n return null;\n }\n const value = String(entry).trim();\n if (value === '') {\n return null;\n }\n return value;\n })\n .filter((entry): entry is string => {\n return entry != null;\n });\n\n if (normalized.length === 0) {\n return null;\n }\n return normalized.join(', ');\n }\n\n if (typeof raw === 'boolean') {\n if (filter.kind === 'boolean') {\n return options.booleanLabel(raw);\n }\n if (raw) {\n return options.fallbackBooleanLabels.yes;\n }\n return options.fallbackBooleanLabels.no;\n }\n\n if (typeof raw !== 'string' && typeof raw !== 'number') {\n return null;\n }\n\n const rawString = String(raw).trim();\n if (rawString === '') {\n return null;\n }\n\n if (filter.kind === 'entityId') {\n return <EntityFilterValue entityId={filter.entity} id={rawString} />;\n }\n\n if (filter.kind === 'enum') {\n return options.enumLabel(rawString);\n }\n\n return rawString;\n};\n\nconst toDatetimeInputValue = (value: string): string => {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) {\n return value;\n }\n const offsetMs = date.getTimezoneOffset() * 60_000;\n return new Date(date.getTime() - offsetMs).toISOString().slice(0, 16);\n};\n\nconst fromDatetimeInputValue = (value: string): string => {\n const normalized = value.trim();\n if (normalized === '') {\n return '';\n }\n const date = new Date(normalized);\n if (Number.isNaN(date.getTime())) {\n return normalized;\n }\n return date.toISOString();\n};\n\ntype RuntimeWhere = Record<string, unknown>;\ntype RuntimeSort = string;\n\ntype Props<RowView> = {\n config: BackofficeRuntimeResolvedListFacetConfig;\n state: BackofficeListState<RuntimeWhere, RuntimeSort>;\n pushState: (next: BackofficeListState<RuntimeWhere, RuntimeSort>) => void;\n header?: {\n title?: string;\n subtitle?: string;\n };\n headerActions?: ReactNode;\n rows: readonly RowView[];\n getRowId: GetRowId<RowView>;\n columns: readonly DataTableColumn<RowView>[];\n gridTemplateColumns?: string;\n hasNextPage: boolean;\n isLoadingMore: boolean;\n isRefreshing?: boolean;\n onLoadMore: () => void;\n onRefresh?: () => void;\n totalCount?: number | null;\n emptyState?: JSX.Element;\n statusBanner?: ReactNode;\n isLoadingInitial?: boolean;\n virtualize?: boolean;\n variant?: 'page' | 'embedded';\n showFilters?: boolean;\n};\n\nexport const BackofficeEntityListScaffold = <RowView,>(\n props: Props<RowView>,\n): JSX.Element | null => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const {\n config,\n state,\n pushState,\n rows,\n getRowId,\n columns,\n gridTemplateColumns,\n hasNextPage,\n isLoadingMore,\n isRefreshing = false,\n onLoadMore,\n onRefresh,\n totalCount,\n emptyState,\n statusBanner,\n header,\n headerActions,\n isLoadingInitial = false,\n variant = 'page',\n showFilters = true,\n } = props;\n const listConfig = config.list;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const listDefaults = config.listDefaults ??\n listConfig.defaultState ?? { where: null, sort: null };\n\n const columnsWithPrimary = useMemo(() => {\n const hasPrimary = columns.some((col) => {\n return col.isPrimary === true;\n });\n if (hasPrimary || columns.length === 0) {\n return columns;\n }\n return columns.map((col, index) => {\n const { header } = col;\n if (index === 0) {\n return { ...col, isPrimary: true, header };\n }\n return { ...col, header };\n });\n }, [columns]);\n\n const chips = useMemo<readonly FilterChip[]>(() => {\n const out: FilterChip[] = [];\n for (const filter of listConfig.filters) {\n const raw = getFilterValue(filter, state.where);\n const displayValue = getFilterDisplayValue(filter, raw, {\n enumLabel: (value) => {\n if (filter.kind !== 'enum') {\n return value;\n }\n const match = filter.options.find((option) => {\n return option.value === value;\n });\n if (match != null) {\n return resolveLabel(match.label, tApp);\n }\n return value;\n },\n booleanLabel: (value) => {\n if (filter.kind === 'boolean') {\n if (value && filter.trueLabel != null) {\n return resolveLabel(filter.trueLabel, tApp);\n }\n if (!value && filter.falseLabel != null) {\n return resolveLabel(filter.falseLabel, tApp);\n }\n }\n if (value) {\n return t('filters.boolean.yes');\n }\n return t('filters.boolean.no');\n },\n fallbackBooleanLabels: {\n yes: t('filters.boolean.yes'),\n no: t('filters.boolean.no'),\n },\n });\n\n if (displayValue != null) {\n let idValue = String(raw);\n if (Array.isArray(raw)) {\n idValue = raw.join(',');\n }\n const label = (\n <span>\n {resolveLabel(filter.label, tApp)}: {displayValue}\n </span>\n );\n out.push({\n id: `${filter.id}:${idValue}`,\n label,\n onRemove: () => {\n const key = filter.whereKey ?? filter.id;\n const nextWhere = setWhereValue(\n state.where,\n key,\n null,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n },\n });\n }\n }\n return out;\n }, [listConfig.filters, pushState, state, t, tApp]);\n\n const handleClearAll = useCallback(() => {\n pushState({\n ...listDefaults,\n });\n }, [listDefaults, pushState]);\n const [isFilterDrawerOpen, setIsFilterDrawerOpen] = useState(false);\n const [filterSearch, setFilterSearch] = useState('');\n\n const [pickerDialog, setPickerDialog] = useState<{\n entity: string;\n whereKey: keyof RuntimeWhere;\n label: string;\n path?: readonly string[];\n scope?: BackofficePickerScope<Record<string, unknown>>;\n } | null>(null);\n\n const renderFilterControl = useCallback(\n (filter: BackofficeFilterSpec<RuntimeWhere>): JSX.Element => {\n const key = filter.whereKey ?? filter.id;\n const candidate = getFilterValue(filter, state.where);\n let value = '';\n if (typeof candidate === 'string') {\n value = candidate;\n }\n if (typeof candidate === 'number' && Number.isFinite(candidate)) {\n value = String(candidate);\n }\n\n const filterLabelText = resolveLabel(filter.label, tApp);\n\n if (filter.kind === 'text') {\n const placeholderLabelText =\n filter.placeholderLabel != null\n ? resolveLabel(filter.placeholderLabel, tApp)\n : filterLabelText;\n let placeholder = t('filters.placeholders.search', {\n label: placeholderLabelText,\n });\n if (filter.placeholderText != null) {\n placeholder = resolveLabel(filter.placeholderText, tApp);\n }\n return (\n <DeferredFilterSearchInput\n value={toDatetimeInputValue(value)}\n onApply={(next) => {\n const normalized = fromDatetimeInputValue(next);\n const nextWhere = setWhereValue(\n state.where,\n key,\n normalized,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n placeholder={placeholder}\n ariaLabel={placeholder}\n className={styles.filterInput}\n />\n );\n }\n\n if (filter.kind === 'datetime') {\n const placeholderLabelText =\n filter.placeholderLabel != null\n ? resolveLabel(filter.placeholderLabel, tApp)\n : filterLabelText;\n let placeholder = t('filters.placeholders.search', {\n label: placeholderLabelText,\n });\n if (filter.placeholderText != null) {\n placeholder = resolveLabel(filter.placeholderText, tApp);\n }\n return (\n <DeferredFilterSearchInput\n value={value}\n onApply={(next) => {\n const nextWhere = setWhereValue(\n state.where,\n key,\n next,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n placeholder={placeholder}\n ariaLabel={placeholder}\n className={styles.filterInput}\n type=\"datetime-local\"\n />\n );\n }\n\n if (filter.kind === 'number') {\n const placeholderLabelText =\n filter.placeholderLabel != null\n ? resolveLabel(filter.placeholderLabel, tApp)\n : filterLabelText;\n let placeholder = t('filters.placeholders.search', {\n label: placeholderLabelText,\n });\n if (filter.placeholderText != null) {\n placeholder = resolveLabel(filter.placeholderText, tApp);\n }\n return (\n <DeferredFilterSearchInput\n value={value}\n onApply={(next) => {\n const normalized = next.trim();\n const parsed = normalized === '' ? null : Number(normalized);\n const nextWhere = setWhereValue(\n state.where,\n key,\n Number.isFinite(parsed) ? parsed : null,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n placeholder={placeholder}\n ariaLabel={placeholder}\n className={styles.filterInput}\n inputMode={filter.inputMode ?? 'numeric'}\n type=\"number\"\n />\n );\n }\n\n if (filter.kind === 'enum') {\n const options = [\n {\n id: 'any',\n value: '',\n label: t('filters.all', {\n label: filterLabelText,\n }),\n },\n ...filter.options.map((option) => {\n return {\n id: option.value,\n value: option.value,\n label: resolveLabel(option.label, tApp),\n };\n }),\n ];\n\n return (\n <SimpleSelect\n options={options}\n value={value}\n size=\"small\"\n ariaLabel={filterLabelText}\n onChange={(next) => {\n const nextWhere = setWhereValue(\n state.where,\n key,\n next,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n />\n );\n }\n\n if (filter.kind === 'boolean') {\n let current: boolean | null = null;\n if (typeof candidate === 'boolean') {\n current = candidate;\n }\n\n let selectValue = '';\n if (current === true) {\n selectValue = 'true';\n }\n if (current === false) {\n selectValue = 'false';\n }\n\n const trueLabel =\n filter.trueLabel != null\n ? resolveLabel(filter.trueLabel, tApp)\n : t('filters.boolean.yes');\n const falseLabel =\n filter.falseLabel != null\n ? resolveLabel(filter.falseLabel, tApp)\n : t('filters.boolean.no');\n const options = [\n {\n id: 'any',\n value: '',\n label: t('filters.all', {\n label: filterLabelText,\n }),\n },\n {\n id: 'true',\n value: 'true',\n label: trueLabel,\n },\n {\n id: 'false',\n value: 'false',\n label: falseLabel,\n },\n ];\n\n return (\n <SimpleSelect\n options={options}\n value={selectValue}\n size=\"small\"\n ariaLabel={filterLabelText}\n onChange={(next) => {\n let parsed: boolean | null = null;\n if (next === 'true') {\n parsed = true;\n }\n if (next === 'false') {\n parsed = false;\n }\n const nextWhere = setWhereValue(\n state.where,\n key,\n parsed,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n />\n );\n }\n\n const pickerScope = (() => {\n if (filter.pickerScope == null) {\n return undefined;\n }\n if (typeof filter.pickerScope === 'function') {\n return filter.pickerScope(state.where);\n }\n return filter.pickerScope;\n })();\n let currentId: string | null = null;\n if (typeof candidate === 'string') {\n currentId = candidate;\n }\n\n const renderField = (\n displayValue: string | null = null,\n isResolving = false,\n ) => {\n const normalizedDisplayValue = displayValue?.trim() ?? '';\n return (\n <EntityIdFilterField\n label={filterLabelText}\n value={currentId}\n displayValue={normalizedDisplayValue}\n isResolving={isResolving}\n placeholder={t('filters.placeholders.anyEntity', {\n label: filterLabelText,\n })}\n onPick={() => {\n setPickerDialog({\n entity: filter.entity,\n whereKey: key,\n label: filterLabelText,\n path: filter.path,\n scope: pickerScope,\n });\n }}\n onClear={() => {\n const nextWhere = setWhereValue(\n state.where,\n key,\n null,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n />\n );\n };\n\n if (currentId == null || currentId.trim() === '') {\n return renderField();\n }\n\n return (\n <EntityFilterValueText entityId={filter.entity} id={currentId}>\n {(label, valueState) => {\n const isResolving = valueState?.status === 'loading';\n return renderField(\n isResolving ? t('common.loading') : label,\n isResolving,\n );\n }}\n </EntityFilterValueText>\n );\n },\n [pushState, state, t, tApp],\n );\n\n const hasPlacementConfig = useMemo(() => {\n return listConfig.filters.some((filter) => {\n return filter.placement != null;\n });\n }, [listConfig.filters]);\n\n const quickFilters = useMemo(() => {\n if (listConfig.filters.length === 0) {\n return [];\n }\n const maxPromotedFilters = listConfig.ui?.toolbar?.maxPromotedFilters ?? 3;\n if (hasPlacementConfig) {\n return listConfig.filters.filter((filter) => {\n return filter.placement === 'quick' || filter.placement === 'both';\n });\n }\n return listConfig.filters.slice(0, maxPromotedFilters);\n }, [listConfig.filters, listConfig.ui?.toolbar, hasPlacementConfig]);\n\n const drawerFilters = useMemo(() => {\n return listConfig.filters.filter((filter) => {\n if (filter.placement == null) {\n return true;\n }\n return filter.placement === 'drawer' || filter.placement === 'both';\n });\n }, [listConfig.filters]);\n\n const searchFilter = useMemo(() => {\n return quickFilters.find((filter) => {\n return filter.kind === 'text';\n });\n }, [quickFilters]);\n\n const quickFiltersNode = useMemo(() => {\n const visibleQuickFilters = quickFilters.filter((filter) => {\n return filter !== searchFilter;\n });\n\n if (visibleQuickFilters.length === 0) {\n return null;\n }\n\n return (\n <div className={styles.controlsRow}>\n {visibleQuickFilters.map((filter) => {\n return <span key={filter.id}>{renderFilterControl(filter)}</span>;\n })}\n </div>\n );\n }, [quickFilters, renderFilterControl, searchFilter]);\n\n const searchNode = useMemo(() => {\n if (searchFilter == null) {\n return null;\n }\n return renderFilterControl(searchFilter);\n }, [renderFilterControl, searchFilter]);\n\n const sortNode = useMemo(() => {\n if (listConfig.sorts.length === 0) {\n return null;\n }\n const firstSort = listConfig.sorts[0];\n if (firstSort == null) {\n return null;\n }\n const options = listConfig.sorts.map((s) => {\n return { id: s.id, value: s.id, label: resolveLabel(s.label, tApp) };\n });\n return (\n <SimpleSelect\n options={options}\n value={state.sort ?? firstSort.id}\n size=\"small\"\n ariaLabel={t('list.sort.label')}\n onChange={(next) => {\n pushState({\n ...state,\n sort: next,\n });\n }}\n />\n );\n }, [listConfig.sorts, pushState, state, t, tApp]);\n\n const chipsNode = useMemo(() => {\n if (chips.length === 0) {\n return null;\n }\n return <FilterChipRow chips={chips} onClearAll={handleClearAll} />;\n }, [chips, handleClearAll]);\n\n const drawerSections = useMemo(() => {\n if (drawerFilters.length === 0) {\n return [];\n }\n\n const normalizedQuery = filterSearch.trim().toLowerCase();\n const items: { id: string; node: JSX.Element }[] = [];\n\n for (const filter of drawerFilters) {\n const resolvedLabel = resolveLabel(filter.label, tApp);\n const matchesQuery =\n normalizedQuery === '' ||\n resolvedLabel.toLowerCase().includes(normalizedQuery);\n\n if (matchesQuery) {\n items.push({\n id: filter.id,\n node: (\n <BackofficeFilterField label={resolvedLabel}>\n {renderFilterControl(filter)}\n </BackofficeFilterField>\n ),\n });\n }\n }\n\n if (items.length === 0) {\n return [];\n }\n\n return [\n {\n id: 'backoffice.filters.sections.default',\n title: t('filters.sections.default'),\n items,\n },\n ];\n }, [drawerFilters, filterSearch, renderFilterControl, t, tApp]);\n\n const allFiltersNode = useMemo(() => {\n if (drawerFilters.length === 0) {\n return null;\n }\n const activeCount = chips.length;\n let label = t('filters.trigger');\n if (activeCount > 0) {\n label = t('filters.triggerWithCount', {\n count: activeCount,\n });\n }\n return (\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={() => {\n setIsFilterDrawerOpen(true);\n }}\n >\n {label}\n </Button>\n );\n }, [chips.length, drawerFilters.length, t]);\n\n const filterDrawerEmptyLabel =\n filterSearch.trim() === ''\n ? undefined\n : t('filters.drawer.emptySearchResults');\n\n const filterDrawerNode = (\n <BackofficeFilterDrawer\n isOpen={isFilterDrawerOpen}\n onClose={() => {\n setIsFilterDrawerOpen(false);\n setFilterSearch('');\n }}\n sections={drawerSections}\n searchValue={filterSearch}\n onSearchChange={(next) => {\n setFilterSearch(next);\n }}\n onReset={handleClearAll}\n emptyLabel={filterDrawerEmptyLabel}\n />\n );\n\n const resolvedEmptyState = useMemo((): JSX.Element => {\n if (emptyState != null) {\n return emptyState;\n }\n\n if (isLoadingInitial) {\n return (\n <BackofficeTableSkeleton\n variant=\"embedded\"\n ariaLabel={t('common.loading')}\n />\n );\n }\n\n if (chips.length > 0) {\n return (\n <BackofficeEmptyState\n title={t('emptyState.listEmpty.title')}\n description={t('emptyState.listEmptyFiltered.description')}\n actions={\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={handleClearAll}\n >\n {t('emptyState.listEmptyFiltered.actions.reset')}\n </Button>\n }\n />\n );\n }\n\n return (\n <BackofficeEmptyState\n title={t('emptyState.listEmpty.title')}\n description={t('emptyState.listEmpty.description')}\n />\n );\n }, [chips.length, emptyState, handleClearAll, isLoadingInitial, t]);\n\n const tableFooterMeta = useMemo(() => {\n if (typeof totalCount !== 'number') {\n if (rows.length === 0) {\n return null;\n }\n return (\n <span>\n {t('list.loaded', {\n count: rows.length,\n })}\n </span>\n );\n }\n return (\n <span>\n {t('list.showing', {\n shown: rows.length,\n total: totalCount,\n })}\n </span>\n );\n }, [rows.length, t, totalCount]);\n\n const runtimeConfig = useMemo(() => {\n const resolvedDisplayMode =\n listConfig.ui?.displayMode ?? listConfig.responsive?.mode ?? 'auto';\n return resolveBackofficeListRuntimeConfig({\n kind: listConfig.kind,\n displayMode: resolvedDisplayMode,\n ui: listConfig.ui,\n });\n }, [listConfig.kind, listConfig.responsive?.mode, listConfig.ui]);\n\n const hasKnownRemainingRows =\n typeof totalCount === 'number' && rows.length < totalCount;\n const hasInconsistentPageInfo = hasKnownRemainingRows && !hasNextPage;\n\n useEffect(() => {\n if (\n !hasInconsistentPageInfo ||\n !runtimeConfig.infiniteScroll.showInconsistentPageInfo ||\n !isDevEnv()\n ) {\n return;\n }\n // eslint-disable-next-line no-console\n console.warn(\n 'Backoffice list received inconsistent pageInfo: loaded rows are lower than totalCount but hasNextPage is false.',\n {\n entityId: config.id,\n loadedCount: rows.length,\n totalCount,\n },\n );\n }, [\n config.id,\n hasInconsistentPageInfo,\n rows.length,\n runtimeConfig.infiniteScroll.showInconsistentPageInfo,\n totalCount,\n ]);\n\n const shouldVirtualizeTable =\n props.virtualize === true || runtimeConfig.virtualization.enabled;\n\n const { sentinelRef } = useBackofficeInfiniteScrollSentinel({\n enabled: !shouldVirtualizeTable && runtimeConfig.infiniteScroll.enabled,\n hasNextPage,\n isLoading: isLoadingMore,\n onIntersect: onLoadMore,\n rootMargin: runtimeConfig.infiniteScroll.rootMargin,\n threshold: runtimeConfig.infiniteScroll.threshold,\n });\n\n const headerTitle = header?.title ?? resolveLabel(listConfig.title, tApp);\n const headerSubtitle = header?.subtitle;\n\n const actionColumn = columnsWithPrimary.find((column) => {\n return column.mobileRole === 'action' || column.id === 'actions';\n });\n const listMode =\n listConfig.ui?.displayMode ?? listConfig.responsive?.mode ?? 'auto';\n const listDensity =\n listConfig.ui?.density ?? listConfig.responsive?.density ?? 'compact';\n\n const tableInnerNode = shouldVirtualizeTable ? (\n <BackofficeVirtualizedConnectionTable\n columns={columnsWithPrimary}\n rows={rows}\n getRowId={getRowId}\n emptyState={resolvedEmptyState}\n className={denseTableClass}\n gridTemplateColumns={gridTemplateColumns}\n virtualization={runtimeConfig.virtualization}\n infiniteScroll={{\n enabled: runtimeConfig.infiniteScroll.enabled,\n thresholdPx: runtimeConfig.infiniteScroll.thresholdPx,\n autoLoad: runtimeConfig.infiniteScroll.autoLoad,\n }}\n hasNextPage={hasNextPage}\n isLoadingMore={isLoadingMore}\n onLoadMore={onLoadMore}\n />\n ) : (\n <ResponsiveRecordList\n columns={columnsWithPrimary}\n rows={rows}\n getRowId={getRowId}\n emptyState={resolvedEmptyState}\n className={denseTableClass}\n gridTemplateColumns={gridTemplateColumns}\n mode={listMode}\n density={listDensity}\n renderAction={(row) => {\n return actionColumn?.cell(row) ?? null;\n }}\n />\n );\n\n const tableNodeWithErrorBoundary = (\n <BackofficeErrorBoundary\n fallback={(args: { error: unknown; reset: () => void }) => {\n const { reset } = args;\n\n const retry = (): void => {\n reset();\n if (onRefresh != null) {\n onRefresh();\n }\n };\n\n return (\n <InlineBanner\n tone=\"danger\"\n title={t('list.errors.title')}\n actions={\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={retry}\n >\n {t('list.actions.retry')}\n </Button>\n }\n >\n {t('list.errors.tableFailed')}\n </InlineBanner>\n );\n }}\n >\n {tableInnerNode}\n </BackofficeErrorBoundary>\n );\n\n const filtersBarNode = showFilters ? (\n <>\n <BackofficeListToolbar\n primaryFilters={\n searchNode != null || quickFiltersNode != null ? (\n <>\n {searchNode}\n {quickFiltersNode}\n </>\n ) : null\n }\n filterDrawerTrigger={allFiltersNode}\n sortControl={sortNode}\n utilityActions={\n onRefresh == null ? null : (\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n isLoading={isRefreshing}\n loadingLabel={t('list.actions.refreshing')}\n onClick={() => {\n onRefresh();\n }}\n >\n {t('list.actions.refresh')}\n </Button>\n )\n }\n activeFilters={chipsNode}\n density=\"compact\"\n />\n {filterDrawerNode}\n </>\n ) : null;\n\n const tableNode = (\n <div>\n {tableNodeWithErrorBoundary}\n <EntityIdPickerDialog\n isOpen={pickerDialog != null}\n entity={pickerDialog?.entity ?? config.id}\n title={pickerDialog?.label ?? t('picker.title')}\n scope={pickerDialog?.scope}\n onClose={() => {\n setPickerDialog(null);\n }}\n onSelectId={(id) => {\n if (pickerDialog == null) {\n return;\n }\n const nextWhere = setWhereValue(\n state.where,\n pickerDialog.whereKey,\n id,\n pickerDialog.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n />\n </div>\n );\n\n const shouldRenderTableFooter =\n rows.length > 0 || isLoadingMore || hasNextPage;\n\n const tableFooterNode = shouldRenderTableFooter ? (\n <>\n {!shouldVirtualizeTable && <div ref={sentinelRef} aria-hidden=\"true\" />}\n <BackofficeInfiniteListStatus\n loadedCount={rows.length}\n totalCount={totalCount}\n hasNextPage={hasNextPage}\n isLoading={isLoadingMore}\n pageInfoState={\n hasInconsistentPageInfo\n ? 'inconsistent'\n : isLoadingMore\n ? 'loading'\n : hasNextPage\n ? 'ready'\n : 'complete'\n }\n loadedLabel={tableFooterMeta}\n loadingLabel={t('list.loadMore.loading')}\n endLabel={t('list.loadMore.end')}\n />\n </>\n ) : null;\n\n if (variant === 'embedded') {\n return (\n <BackofficeListFilterProvider\n config={config}\n state={state}\n pushState={pushState}\n >\n <div className={styles.embeddedContainer}>\n <div className={styles.embeddedHeader}>{headerTitle}</div>\n {filtersBarNode}\n {statusBanner}\n {tableNode}\n {tableFooterNode}\n </div>\n </BackofficeListFilterProvider>\n );\n }\n\n return (\n <BackofficeListFilterProvider\n config={config}\n state={state}\n pushState={pushState}\n >\n <ListPageTemplate\n headerNode={\n <BackofficePageHeader\n title={headerTitle}\n subtitle={headerSubtitle}\n actions={headerActions}\n />\n }\n toolbarNode={filtersBarNode}\n statusNode={statusBanner}\n tableNode={tableNode}\n tableFooterNode={tableFooterNode}\n presentation=\"flat\"\n />\n </BackofficeListFilterProvider>\n );\n};\n\nexport default BackofficeEntityListScaffold;\n"],"mappings":"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"}
1
+ {"version":3,"file":"BackofficeEntityListScaffold.js","names":[],"sources":["../../../../../src/components/backoffice/scaffolds/BackofficeEntityListScaffold.tsx"],"sourcesContent":["/* eslint-disable no-ternary */\nimport {\n type JSX,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport type { TFunction } from 'i18next';\nimport { useTranslation } from 'react-i18next';\nimport { Button } from '@plumile/ui/atomic/atoms/button/Button.js';\nimport { BackofficeEmptyState } from '@plumile/ui/backoffice/molecules/backoffice_empty_state/BackofficeEmptyState.js';\nimport { BackofficeFilterDrawer } from '@plumile/ui/backoffice/molecules/backoffice_filter_drawer/BackofficeFilterDrawer.js';\nimport { BackofficeFilterField } from '@plumile/ui/backoffice/molecules/backoffice_filter_field/BackofficeFilterField.js';\nimport { BackofficeInfiniteListStatus } from '@plumile/ui/backoffice/molecules/backoffice_infinite_list_status/BackofficeInfiniteListStatus.js';\nimport { BackofficePageHeader } from '@plumile/ui/backoffice/molecules/backoffice_page_header/BackofficePageHeader.js';\nimport { BackofficeTableSkeleton } from '@plumile/ui/backoffice/molecules/backoffice_table_skeleton/BackofficeTableSkeleton.js';\nimport {\n FilterChipRow,\n type FilterChip,\n} from '@plumile/ui/backoffice/molecules/filter_chip_row/FilterChipRow.js';\nimport { InlineBanner } from '@plumile/ui/backoffice/molecules/inline_banner/InlineBanner.js';\nimport { BackofficeVirtualizedConnectionTable } from '@plumile/ui/backoffice/organisms/backoffice_virtualized_connection_table/BackofficeVirtualizedConnectionTable.js';\nimport { ListPageTemplate } from '@plumile/ui/backoffice/templates/list_page_template/ListPageTemplate.js';\nimport {\n type DataTableColumn,\n type GetRowId,\n} from '@plumile/ui/components/data-table/DataTable.js';\nimport { ResponsiveRecordList } from '@plumile/ui/components/data-table/ResponsiveRecordList.js';\nimport { SimpleSelect } from '@plumile/ui/components/select/SimpleSelect.js';\nimport { denseTableClass } from '@plumile/ui/shared/backofficeTableDensity.css.js';\n\nimport {\n readWhereValue,\n setWhereValue,\n} from '@plumile/backoffice-core/filters/where.js';\nimport { resolveBackofficeListRuntimeConfig } from '@plumile/backoffice-core/config/listRuntime.js';\nimport type {\n BackofficeFilterSpec,\n BackofficeListState,\n BackofficePickerScope,\n BackofficeRuntimeResolvedListFacetConfig,\n I18nLabel,\n} from '@plumile/backoffice-core/types.js';\n\nimport { BackofficeErrorBoundary } from '../errors/BackofficeErrorBoundary.js';\nimport {\n EntityFilterValue,\n EntityFilterValueText,\n} from '../filters/EntityFilterValue.js';\nimport { EntityIdPickerDialog } from '../pickers/EntityIdPickerDialog.js';\nimport { EntityIdFilterField } from '../filters/EntityIdFilterField.js';\nimport { DeferredFilterSearchInput } from '../filters/DeferredFilterSearchInput.js';\nimport { BackofficeListToolbar } from '../lists/BackofficeListToolbar.js';\nimport { BackofficeListFilterProvider } from './BackofficeListFilterContext.js';\nimport { BACKOFFICE_LIST_BODY_SCROLL_MODE } from './backofficeListScrollMode.js';\nimport { useBackofficeReactTranslation } from '../../../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeInfiniteScrollSentinel } from '../../../hooks/useBackofficeInfiniteScrollSentinel.js';\nimport { isDevEnv } from '../../../relay/envHelpers.js';\n\nimport * as styles from './backofficeEntityListScaffold.css.js';\n\nconst resolveLabel = (label: I18nLabel, tApp: TFunction): string => {\n return label(tApp);\n};\n\nconst getFilterValue = <Where extends Record<string, unknown>>(\n filter: BackofficeFilterSpec<Where>,\n where: Where | null,\n): unknown => {\n if (filter.fromGraphQL != null && where != null) {\n return filter.fromGraphQL(where);\n }\n\n const key = (filter.whereKey ?? filter.id) as keyof Where;\n return readWhereValue(where, key, filter.path);\n};\n\nconst getFilterDisplayValue = <Where extends Record<string, unknown>>(\n filter: BackofficeFilterSpec<Where>,\n raw: unknown,\n options: {\n enumLabel: (value: string) => string;\n booleanLabel: (value: boolean) => string;\n fallbackBooleanLabels: { yes: string; no: string };\n },\n): ReactNode | null => {\n if (raw == null) {\n return null;\n }\n\n if (Array.isArray(raw)) {\n const normalized = raw\n .map((entry) => {\n if (entry == null) {\n return null;\n }\n if (\n typeof entry !== 'string' &&\n typeof entry !== 'number' &&\n typeof entry !== 'boolean'\n ) {\n return null;\n }\n const value = String(entry).trim();\n if (value === '') {\n return null;\n }\n return value;\n })\n .filter((entry): entry is string => {\n return entry != null;\n });\n\n if (normalized.length === 0) {\n return null;\n }\n return normalized.join(', ');\n }\n\n if (typeof raw === 'boolean') {\n if (filter.kind === 'boolean') {\n return options.booleanLabel(raw);\n }\n if (raw) {\n return options.fallbackBooleanLabels.yes;\n }\n return options.fallbackBooleanLabels.no;\n }\n\n if (typeof raw !== 'string' && typeof raw !== 'number') {\n return null;\n }\n\n const rawString = String(raw).trim();\n if (rawString === '') {\n return null;\n }\n\n if (filter.kind === 'entityId') {\n return <EntityFilterValue entityId={filter.entity} id={rawString} />;\n }\n\n if (filter.kind === 'enum') {\n return options.enumLabel(rawString);\n }\n\n return rawString;\n};\n\nconst toDatetimeInputValue = (value: string): string => {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) {\n return value;\n }\n const offsetMs = date.getTimezoneOffset() * 60_000;\n return new Date(date.getTime() - offsetMs).toISOString().slice(0, 16);\n};\n\nconst fromDatetimeInputValue = (value: string): string => {\n const normalized = value.trim();\n if (normalized === '') {\n return '';\n }\n const date = new Date(normalized);\n if (Number.isNaN(date.getTime())) {\n return normalized;\n }\n return date.toISOString();\n};\n\ntype RuntimeWhere = Record<string, unknown>;\ntype RuntimeSort = string;\n\ntype Props<RowView> = {\n config: BackofficeRuntimeResolvedListFacetConfig;\n state: BackofficeListState<RuntimeWhere, RuntimeSort>;\n pushState: (next: BackofficeListState<RuntimeWhere, RuntimeSort>) => void;\n header?: {\n title?: string;\n subtitle?: string;\n };\n headerActions?: ReactNode;\n rows: readonly RowView[];\n getRowId: GetRowId<RowView>;\n columns: readonly DataTableColumn<RowView>[];\n gridTemplateColumns?: string;\n hasNextPage: boolean;\n isLoadingMore: boolean;\n isRefreshing?: boolean;\n onLoadMore: () => void;\n onRefresh?: () => void;\n totalCount?: number | null;\n emptyState?: JSX.Element;\n statusBanner?: ReactNode;\n isLoadingInitial?: boolean;\n virtualize?: boolean;\n variant?: 'page' | 'embedded';\n showFilters?: boolean;\n};\n\nexport const BackofficeEntityListScaffold = <RowView,>(\n props: Props<RowView>,\n): JSX.Element | null => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const {\n config,\n state,\n pushState,\n rows,\n getRowId,\n columns,\n gridTemplateColumns,\n hasNextPage,\n isLoadingMore,\n isRefreshing = false,\n onLoadMore,\n onRefresh,\n totalCount,\n emptyState,\n statusBanner,\n header,\n headerActions,\n isLoadingInitial = false,\n variant = 'page',\n showFilters = true,\n } = props;\n const listConfig = config.list;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const listDefaults = config.listDefaults ??\n listConfig.defaultState ?? { where: null, sort: null };\n\n const columnsWithPrimary = useMemo(() => {\n const hasPrimary = columns.some((col) => {\n return col.isPrimary === true;\n });\n if (hasPrimary || columns.length === 0) {\n return columns;\n }\n return columns.map((col, index) => {\n const { header } = col;\n if (index === 0) {\n return { ...col, isPrimary: true, header };\n }\n return { ...col, header };\n });\n }, [columns]);\n\n const chips = useMemo<readonly FilterChip[]>(() => {\n const out: FilterChip[] = [];\n for (const filter of listConfig.filters) {\n const raw = getFilterValue(filter, state.where);\n const displayValue = getFilterDisplayValue(filter, raw, {\n enumLabel: (value) => {\n if (filter.kind !== 'enum') {\n return value;\n }\n const match = filter.options.find((option) => {\n return option.value === value;\n });\n if (match != null) {\n return resolveLabel(match.label, tApp);\n }\n return value;\n },\n booleanLabel: (value) => {\n if (filter.kind === 'boolean') {\n if (value && filter.trueLabel != null) {\n return resolveLabel(filter.trueLabel, tApp);\n }\n if (!value && filter.falseLabel != null) {\n return resolveLabel(filter.falseLabel, tApp);\n }\n }\n if (value) {\n return t('filters.boolean.yes');\n }\n return t('filters.boolean.no');\n },\n fallbackBooleanLabels: {\n yes: t('filters.boolean.yes'),\n no: t('filters.boolean.no'),\n },\n });\n\n if (displayValue != null) {\n let idValue = String(raw);\n if (Array.isArray(raw)) {\n idValue = raw.join(',');\n }\n const label = (\n <span>\n {resolveLabel(filter.label, tApp)}: {displayValue}\n </span>\n );\n out.push({\n id: `${filter.id}:${idValue}`,\n label,\n onRemove: () => {\n const key = filter.whereKey ?? filter.id;\n const nextWhere = setWhereValue(\n state.where,\n key,\n null,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n },\n });\n }\n }\n return out;\n }, [listConfig.filters, pushState, state, t, tApp]);\n\n const handleClearAll = useCallback(() => {\n pushState({\n ...listDefaults,\n });\n }, [listDefaults, pushState]);\n const [isFilterDrawerOpen, setIsFilterDrawerOpen] = useState(false);\n const [filterSearch, setFilterSearch] = useState('');\n\n const [pickerDialog, setPickerDialog] = useState<{\n entity: string;\n whereKey: keyof RuntimeWhere;\n label: string;\n path?: readonly string[];\n scope?: BackofficePickerScope<Record<string, unknown>>;\n } | null>(null);\n\n const renderFilterControl = useCallback(\n (filter: BackofficeFilterSpec<RuntimeWhere>): JSX.Element => {\n const key = filter.whereKey ?? filter.id;\n const candidate = getFilterValue(filter, state.where);\n let value = '';\n if (typeof candidate === 'string') {\n value = candidate;\n }\n if (typeof candidate === 'number' && Number.isFinite(candidate)) {\n value = String(candidate);\n }\n\n const filterLabelText = resolveLabel(filter.label, tApp);\n\n if (filter.kind === 'text') {\n const placeholderLabelText =\n filter.placeholderLabel != null\n ? resolveLabel(filter.placeholderLabel, tApp)\n : filterLabelText;\n let placeholder = t('filters.placeholders.search', {\n label: placeholderLabelText,\n });\n if (filter.placeholderText != null) {\n placeholder = resolveLabel(filter.placeholderText, tApp);\n }\n return (\n <DeferredFilterSearchInput\n value={toDatetimeInputValue(value)}\n onApply={(next) => {\n const normalized = fromDatetimeInputValue(next);\n const nextWhere = setWhereValue(\n state.where,\n key,\n normalized,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n placeholder={placeholder}\n ariaLabel={placeholder}\n className={styles.filterInput}\n />\n );\n }\n\n if (filter.kind === 'datetime') {\n const placeholderLabelText =\n filter.placeholderLabel != null\n ? resolveLabel(filter.placeholderLabel, tApp)\n : filterLabelText;\n let placeholder = t('filters.placeholders.search', {\n label: placeholderLabelText,\n });\n if (filter.placeholderText != null) {\n placeholder = resolveLabel(filter.placeholderText, tApp);\n }\n return (\n <DeferredFilterSearchInput\n value={value}\n onApply={(next) => {\n const nextWhere = setWhereValue(\n state.where,\n key,\n next,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n placeholder={placeholder}\n ariaLabel={placeholder}\n className={styles.filterInput}\n type=\"datetime-local\"\n />\n );\n }\n\n if (filter.kind === 'number') {\n const placeholderLabelText =\n filter.placeholderLabel != null\n ? resolveLabel(filter.placeholderLabel, tApp)\n : filterLabelText;\n let placeholder = t('filters.placeholders.search', {\n label: placeholderLabelText,\n });\n if (filter.placeholderText != null) {\n placeholder = resolveLabel(filter.placeholderText, tApp);\n }\n return (\n <DeferredFilterSearchInput\n value={value}\n onApply={(next) => {\n const normalized = next.trim();\n const parsed = normalized === '' ? null : Number(normalized);\n const nextWhere = setWhereValue(\n state.where,\n key,\n Number.isFinite(parsed) ? parsed : null,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n placeholder={placeholder}\n ariaLabel={placeholder}\n className={styles.filterInput}\n inputMode={filter.inputMode ?? 'numeric'}\n type=\"number\"\n />\n );\n }\n\n if (filter.kind === 'enum') {\n const options = [\n {\n id: 'any',\n value: '',\n label: t('filters.all', {\n label: filterLabelText,\n }),\n },\n ...filter.options.map((option) => {\n return {\n id: option.value,\n value: option.value,\n label: resolveLabel(option.label, tApp),\n };\n }),\n ];\n\n return (\n <SimpleSelect\n options={options}\n value={value}\n size=\"small\"\n ariaLabel={filterLabelText}\n onChange={(next) => {\n const nextWhere = setWhereValue(\n state.where,\n key,\n next,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n />\n );\n }\n\n if (filter.kind === 'boolean') {\n let current: boolean | null = null;\n if (typeof candidate === 'boolean') {\n current = candidate;\n }\n\n let selectValue = '';\n if (current === true) {\n selectValue = 'true';\n }\n if (current === false) {\n selectValue = 'false';\n }\n\n const trueLabel =\n filter.trueLabel != null\n ? resolveLabel(filter.trueLabel, tApp)\n : t('filters.boolean.yes');\n const falseLabel =\n filter.falseLabel != null\n ? resolveLabel(filter.falseLabel, tApp)\n : t('filters.boolean.no');\n const options = [\n {\n id: 'any',\n value: '',\n label: t('filters.all', {\n label: filterLabelText,\n }),\n },\n {\n id: 'true',\n value: 'true',\n label: trueLabel,\n },\n {\n id: 'false',\n value: 'false',\n label: falseLabel,\n },\n ];\n\n return (\n <SimpleSelect\n options={options}\n value={selectValue}\n size=\"small\"\n ariaLabel={filterLabelText}\n onChange={(next) => {\n let parsed: boolean | null = null;\n if (next === 'true') {\n parsed = true;\n }\n if (next === 'false') {\n parsed = false;\n }\n const nextWhere = setWhereValue(\n state.where,\n key,\n parsed,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n />\n );\n }\n\n const pickerScope = (() => {\n if (filter.pickerScope == null) {\n return undefined;\n }\n if (typeof filter.pickerScope === 'function') {\n return filter.pickerScope(state.where);\n }\n return filter.pickerScope;\n })();\n let currentId: string | null = null;\n if (typeof candidate === 'string') {\n currentId = candidate;\n }\n\n const renderField = (\n displayValue: string | null = null,\n isResolving = false,\n ) => {\n const normalizedDisplayValue = displayValue?.trim() ?? '';\n return (\n <EntityIdFilterField\n label={filterLabelText}\n value={currentId}\n displayValue={normalizedDisplayValue}\n isResolving={isResolving}\n placeholder={t('filters.placeholders.anyEntity', {\n label: filterLabelText,\n })}\n onPick={() => {\n setPickerDialog({\n entity: filter.entity,\n whereKey: key,\n label: filterLabelText,\n path: filter.path,\n scope: pickerScope,\n });\n }}\n onClear={() => {\n const nextWhere = setWhereValue(\n state.where,\n key,\n null,\n filter.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n />\n );\n };\n\n if (currentId == null || currentId.trim() === '') {\n return renderField();\n }\n\n return (\n <EntityFilterValueText entityId={filter.entity} id={currentId}>\n {(label, valueState) => {\n const isResolving = valueState?.status === 'loading';\n return renderField(\n isResolving ? t('common.loading') : label,\n isResolving,\n );\n }}\n </EntityFilterValueText>\n );\n },\n [pushState, state, t, tApp],\n );\n\n const hasPlacementConfig = useMemo(() => {\n return listConfig.filters.some((filter) => {\n return filter.placement != null;\n });\n }, [listConfig.filters]);\n\n const quickFilters = useMemo(() => {\n if (listConfig.filters.length === 0) {\n return [];\n }\n const maxPromotedFilters = listConfig.ui?.toolbar?.maxPromotedFilters ?? 3;\n if (hasPlacementConfig) {\n return listConfig.filters.filter((filter) => {\n return filter.placement === 'quick' || filter.placement === 'both';\n });\n }\n return listConfig.filters.slice(0, maxPromotedFilters);\n }, [listConfig.filters, listConfig.ui?.toolbar, hasPlacementConfig]);\n\n const drawerFilters = useMemo(() => {\n return listConfig.filters.filter((filter) => {\n if (filter.placement == null) {\n return true;\n }\n return filter.placement === 'drawer' || filter.placement === 'both';\n });\n }, [listConfig.filters]);\n\n const searchFilter = useMemo(() => {\n return quickFilters.find((filter) => {\n return filter.kind === 'text';\n });\n }, [quickFilters]);\n\n const quickFiltersNode = useMemo(() => {\n const visibleQuickFilters = quickFilters.filter((filter) => {\n return filter !== searchFilter;\n });\n\n if (visibleQuickFilters.length === 0) {\n return null;\n }\n\n return (\n <div className={styles.controlsRow}>\n {visibleQuickFilters.map((filter) => {\n return <span key={filter.id}>{renderFilterControl(filter)}</span>;\n })}\n </div>\n );\n }, [quickFilters, renderFilterControl, searchFilter]);\n\n const searchNode = useMemo(() => {\n if (searchFilter == null) {\n return null;\n }\n return renderFilterControl(searchFilter);\n }, [renderFilterControl, searchFilter]);\n\n const sortNode = useMemo(() => {\n if (listConfig.sorts.length === 0) {\n return null;\n }\n const firstSort = listConfig.sorts[0];\n if (firstSort == null) {\n return null;\n }\n const options = listConfig.sorts.map((s) => {\n return { id: s.id, value: s.id, label: resolveLabel(s.label, tApp) };\n });\n return (\n <SimpleSelect\n options={options}\n value={state.sort ?? firstSort.id}\n size=\"small\"\n ariaLabel={t('list.sort.label')}\n onChange={(next) => {\n pushState({\n ...state,\n sort: next,\n });\n }}\n />\n );\n }, [listConfig.sorts, pushState, state, t, tApp]);\n\n const chipsNode = useMemo(() => {\n if (chips.length === 0) {\n return null;\n }\n return <FilterChipRow chips={chips} onClearAll={handleClearAll} />;\n }, [chips, handleClearAll]);\n\n const drawerSections = useMemo(() => {\n if (drawerFilters.length === 0) {\n return [];\n }\n\n const normalizedQuery = filterSearch.trim().toLowerCase();\n const items: { id: string; node: JSX.Element }[] = [];\n\n for (const filter of drawerFilters) {\n const resolvedLabel = resolveLabel(filter.label, tApp);\n const matchesQuery =\n normalizedQuery === '' ||\n resolvedLabel.toLowerCase().includes(normalizedQuery);\n\n if (matchesQuery) {\n items.push({\n id: filter.id,\n node: (\n <BackofficeFilterField label={resolvedLabel}>\n {renderFilterControl(filter)}\n </BackofficeFilterField>\n ),\n });\n }\n }\n\n if (items.length === 0) {\n return [];\n }\n\n return [\n {\n id: 'backoffice.filters.sections.default',\n title: t('filters.sections.default'),\n items,\n },\n ];\n }, [drawerFilters, filterSearch, renderFilterControl, t, tApp]);\n\n const allFiltersNode = useMemo(() => {\n if (drawerFilters.length === 0) {\n return null;\n }\n const activeCount = chips.length;\n let label = t('filters.trigger');\n if (activeCount > 0) {\n label = t('filters.triggerWithCount', {\n count: activeCount,\n });\n }\n return (\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={() => {\n setIsFilterDrawerOpen(true);\n }}\n >\n {label}\n </Button>\n );\n }, [chips.length, drawerFilters.length, t]);\n\n const filterDrawerEmptyLabel =\n filterSearch.trim() === ''\n ? undefined\n : t('filters.drawer.emptySearchResults');\n\n const filterDrawerNode = (\n <BackofficeFilterDrawer\n isOpen={isFilterDrawerOpen}\n onClose={() => {\n setIsFilterDrawerOpen(false);\n setFilterSearch('');\n }}\n sections={drawerSections}\n searchValue={filterSearch}\n onSearchChange={(next) => {\n setFilterSearch(next);\n }}\n onReset={handleClearAll}\n emptyLabel={filterDrawerEmptyLabel}\n />\n );\n\n const resolvedEmptyState = useMemo((): JSX.Element => {\n if (emptyState != null) {\n return emptyState;\n }\n\n if (isLoadingInitial) {\n return (\n <BackofficeTableSkeleton\n variant=\"embedded\"\n ariaLabel={t('common.loading')}\n />\n );\n }\n\n if (chips.length > 0) {\n return (\n <BackofficeEmptyState\n title={t('emptyState.listEmpty.title')}\n description={t('emptyState.listEmptyFiltered.description')}\n actions={\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={handleClearAll}\n >\n {t('emptyState.listEmptyFiltered.actions.reset')}\n </Button>\n }\n />\n );\n }\n\n return (\n <BackofficeEmptyState\n title={t('emptyState.listEmpty.title')}\n description={t('emptyState.listEmpty.description')}\n />\n );\n }, [chips.length, emptyState, handleClearAll, isLoadingInitial, t]);\n\n const tableFooterMeta = useMemo(() => {\n if (typeof totalCount !== 'number') {\n if (rows.length === 0) {\n return null;\n }\n return (\n <span>\n {t('list.loaded', {\n count: rows.length,\n })}\n </span>\n );\n }\n return (\n <span>\n {t('list.showing', {\n shown: rows.length,\n total: totalCount,\n })}\n </span>\n );\n }, [rows.length, t, totalCount]);\n\n const runtimeConfig = useMemo(() => {\n const resolvedDisplayMode =\n listConfig.ui?.displayMode ?? listConfig.responsive?.mode ?? 'auto';\n return resolveBackofficeListRuntimeConfig({\n kind: listConfig.kind,\n displayMode: resolvedDisplayMode,\n ui: listConfig.ui,\n });\n }, [listConfig.kind, listConfig.responsive?.mode, listConfig.ui]);\n\n const hasKnownRemainingRows =\n typeof totalCount === 'number' && rows.length < totalCount;\n const hasInconsistentPageInfo = hasKnownRemainingRows && !hasNextPage;\n\n useEffect(() => {\n if (\n !hasInconsistentPageInfo ||\n !runtimeConfig.infiniteScroll.showInconsistentPageInfo ||\n !isDevEnv()\n ) {\n return;\n }\n // eslint-disable-next-line no-console\n console.warn(\n 'Backoffice list received inconsistent pageInfo: loaded rows are lower than totalCount but hasNextPage is false.',\n {\n entityId: config.id,\n loadedCount: rows.length,\n totalCount,\n },\n );\n }, [\n config.id,\n hasInconsistentPageInfo,\n rows.length,\n runtimeConfig.infiniteScroll.showInconsistentPageInfo,\n totalCount,\n ]);\n\n const shouldVirtualizeTable =\n props.virtualize === true || runtimeConfig.virtualization.enabled;\n\n const { sentinelRef } = useBackofficeInfiniteScrollSentinel({\n enabled: !shouldVirtualizeTable && runtimeConfig.infiniteScroll.enabled,\n hasNextPage,\n isLoading: isLoadingMore,\n onIntersect: onLoadMore,\n rootMargin: runtimeConfig.infiniteScroll.rootMargin,\n threshold: runtimeConfig.infiniteScroll.threshold,\n });\n\n const headerTitle = header?.title ?? resolveLabel(listConfig.title, tApp);\n const headerSubtitle = header?.subtitle;\n\n const actionColumn = columnsWithPrimary.find((column) => {\n return column.mobileRole === 'action' || column.id === 'actions';\n });\n const listMode =\n listConfig.ui?.displayMode ?? listConfig.responsive?.mode ?? 'auto';\n const listDensity =\n listConfig.ui?.density ?? listConfig.responsive?.density ?? 'compact';\n\n const tableInnerNode = shouldVirtualizeTable ? (\n <BackofficeVirtualizedConnectionTable\n columns={columnsWithPrimary}\n rows={rows}\n getRowId={getRowId}\n emptyState={resolvedEmptyState}\n className={denseTableClass}\n gridTemplateColumns={gridTemplateColumns}\n virtualization={runtimeConfig.virtualization}\n infiniteScroll={{\n enabled: runtimeConfig.infiniteScroll.enabled,\n thresholdPx: runtimeConfig.infiniteScroll.thresholdPx,\n autoLoad: runtimeConfig.infiniteScroll.autoLoad,\n }}\n hasNextPage={hasNextPage}\n isLoadingMore={isLoadingMore}\n onLoadMore={onLoadMore}\n bodyScrollMode={BACKOFFICE_LIST_BODY_SCROLL_MODE}\n />\n ) : (\n <ResponsiveRecordList\n columns={columnsWithPrimary}\n rows={rows}\n getRowId={getRowId}\n emptyState={resolvedEmptyState}\n className={denseTableClass}\n gridTemplateColumns={gridTemplateColumns}\n mode={listMode}\n density={listDensity}\n bodyScrollMode={BACKOFFICE_LIST_BODY_SCROLL_MODE}\n bodyFooterNode={\n runtimeConfig.infiniteScroll.enabled ? (\n <div ref={sentinelRef} aria-hidden=\"true\" />\n ) : null\n }\n renderAction={(row) => {\n return actionColumn?.cell(row) ?? null;\n }}\n />\n );\n\n const tableNodeWithErrorBoundary = (\n <BackofficeErrorBoundary\n fallback={(args: { error: unknown; reset: () => void }) => {\n const { reset } = args;\n\n const retry = (): void => {\n reset();\n if (onRefresh != null) {\n onRefresh();\n }\n };\n\n return (\n <InlineBanner\n tone=\"danger\"\n title={t('list.errors.title')}\n actions={\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={retry}\n >\n {t('list.actions.retry')}\n </Button>\n }\n >\n {t('list.errors.tableFailed')}\n </InlineBanner>\n );\n }}\n >\n {tableInnerNode}\n </BackofficeErrorBoundary>\n );\n\n const filtersBarNode = showFilters ? (\n <>\n <BackofficeListToolbar\n primaryFilters={\n searchNode != null || quickFiltersNode != null ? (\n <>\n {searchNode}\n {quickFiltersNode}\n </>\n ) : null\n }\n filterDrawerTrigger={allFiltersNode}\n sortControl={sortNode}\n utilityActions={\n onRefresh == null ? null : (\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n isLoading={isRefreshing}\n loadingLabel={t('list.actions.refreshing')}\n onClick={() => {\n onRefresh();\n }}\n >\n {t('list.actions.refresh')}\n </Button>\n )\n }\n activeFilters={chipsNode}\n density=\"compact\"\n />\n {filterDrawerNode}\n </>\n ) : null;\n\n const tableNode = (\n <div className={styles.tableHost}>\n {tableNodeWithErrorBoundary}\n <EntityIdPickerDialog\n isOpen={pickerDialog != null}\n entity={pickerDialog?.entity ?? config.id}\n title={pickerDialog?.label ?? t('picker.title')}\n scope={pickerDialog?.scope}\n onClose={() => {\n setPickerDialog(null);\n }}\n onSelectId={(id) => {\n if (pickerDialog == null) {\n return;\n }\n const nextWhere = setWhereValue(\n state.where,\n pickerDialog.whereKey,\n id,\n pickerDialog.path,\n );\n pushState({ ...state, where: nextWhere });\n }}\n />\n </div>\n );\n\n const shouldRenderTableFooter =\n rows.length > 0 || isLoadingMore || hasNextPage;\n\n const tableFooterNode = shouldRenderTableFooter ? (\n <>\n <BackofficeInfiniteListStatus\n loadedCount={rows.length}\n totalCount={totalCount}\n hasNextPage={hasNextPage}\n isLoading={isLoadingMore}\n pageInfoState={\n hasInconsistentPageInfo\n ? 'inconsistent'\n : isLoadingMore\n ? 'loading'\n : hasNextPage\n ? 'ready'\n : 'complete'\n }\n loadedLabel={tableFooterMeta}\n loadingLabel={t('list.loadMore.loading')}\n endLabel={t('list.loadMore.end')}\n />\n </>\n ) : null;\n\n if (variant === 'embedded') {\n return (\n <BackofficeListFilterProvider\n config={config}\n state={state}\n pushState={pushState}\n >\n <div className={styles.embeddedContainer}>\n <div className={styles.embeddedHeader}>{headerTitle}</div>\n {filtersBarNode}\n {statusBanner}\n {tableNode}\n {tableFooterNode}\n </div>\n </BackofficeListFilterProvider>\n );\n }\n\n return (\n <BackofficeListFilterProvider\n config={config}\n state={state}\n pushState={pushState}\n >\n <ListPageTemplate\n headerNode={\n <BackofficePageHeader\n title={headerTitle}\n subtitle={headerSubtitle}\n actions={headerActions}\n />\n }\n toolbarNode={filtersBarNode}\n statusNode={statusBanner}\n tableNode={tableNode}\n tableFooterNode={tableFooterNode}\n presentation=\"flat\"\n bodyScrollMode={BACKOFFICE_LIST_BODY_SCROLL_MODE}\n />\n </BackofficeListFilterProvider>\n );\n};\n\nexport default BackofficeEntityListScaffold;\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  /* empty css */
2
2
  //#region src/components/backoffice/scaffolds/backofficeEntityListScaffold.css.ts
3
- var e = "txvbqb9ip txvbqbajy txvbqbcp txvbqbao7", t = "_8gc5760 txvbqbu4g txvbqbjep", n = "txvbqb9ip txvbqbai7 txvbqbaog", r = "txvbqb97 txvbqbamp txvbqbv9z";
3
+ var e = "txvbqb9ip txvbqbajy txvbqbcp txvbqbao7", t = "_8gc5760 txvbqbu4g txvbqbjep", n = "txvbqb9ip txvbqbai7 txvbqbaog", r = "txvbqb9ip txvbqbai7 txvbqbcgg txvbqbjh7", i = "txvbqb97 txvbqbamp txvbqbv9z";
4
4
  //#endregion
5
- export { e as controlsRow, n as embeddedContainer, r as embeddedHeader, t as filterInput };
5
+ export { e as controlsRow, n as embeddedContainer, i as embeddedHeader, t as filterInput, r as tableHost };
6
6
 
7
7
  //# sourceMappingURL=backofficeEntityListScaffold.css.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"backofficeEntityListScaffold.css.js","names":[],"sources":["../../../../../src/components/backoffice/scaffolds/backofficeEntityListScaffold.css.ts"],"sourcesContent":["import { style } from '@vanilla-extract/css';\nimport { sprinkles } from '@plumile/ui/theme/sprinkles.css.js';\n\nconst MOBILE_MEDIA_QUERY = 'screen and (max-width: 767px)';\n\nexport const controlsRow = sprinkles({\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'center',\n gap: 2,\n});\n\nexport const filterInput = style([\n sprinkles({\n width: 72,\n maxWidth: 'full',\n }),\n {\n '@media': {\n [MOBILE_MEDIA_QUERY]: {\n width: '100%',\n },\n },\n },\n]);\n\nexport const embeddedContainer = sprinkles({\n display: 'flex',\n flexDirection: 'column',\n gap: 3,\n});\n\nexport const embeddedHeader = sprinkles({\n fontSize: 'base',\n fontWeight: 'semibold',\n color: 'text',\n});\n"],"mappings":""}
1
+ {"version":3,"file":"backofficeEntityListScaffold.css.js","names":[],"sources":["../../../../../src/components/backoffice/scaffolds/backofficeEntityListScaffold.css.ts"],"sourcesContent":["import { style } from '@vanilla-extract/css';\nimport { sprinkles } from '@plumile/ui/theme/sprinkles.css.js';\n\nconst MOBILE_MEDIA_QUERY = 'screen and (max-width: 767px)';\n\nexport const controlsRow = sprinkles({\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'center',\n gap: 2,\n});\n\nexport const filterInput = style([\n sprinkles({\n width: 72,\n maxWidth: 'full',\n }),\n {\n '@media': {\n [MOBILE_MEDIA_QUERY]: {\n width: '100%',\n },\n },\n },\n]);\n\nexport const embeddedContainer = sprinkles({\n display: 'flex',\n flexDirection: 'column',\n gap: 3,\n});\n\nexport const tableHost = sprinkles({\n display: 'flex',\n flexDirection: 'column',\n height: 'full',\n minHeight: 0,\n});\n\nexport const embeddedHeader = sprinkles({\n fontSize: 'base',\n fontWeight: 'semibold',\n color: 'text',\n});\n"],"mappings":""}
@@ -0,0 +1,6 @@
1
+ //#region src/components/backoffice/scaffolds/backofficeListScrollMode.ts
2
+ var e = "contained";
3
+ //#endregion
4
+ export { e as BACKOFFICE_LIST_BODY_SCROLL_MODE };
5
+
6
+ //# sourceMappingURL=backofficeListScrollMode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backofficeListScrollMode.js","names":[],"sources":["../../../../../src/components/backoffice/scaffolds/backofficeListScrollMode.ts"],"sourcesContent":["export const BACKOFFICE_LIST_BODY_SCROLL_MODE = 'contained' as const;\n"],"mappings":";AAAA,IAAa,IAAmC"}
@@ -243,6 +243,7 @@ var ge = "plumile:backoffice:recent-items", _e = "plumile:backoffice:sidebar", v
243
243
  navigationAriaLabel: b("sidebar.navigationAriaLabel")
244
244
  },
245
245
  topbar: { breadcrumb: /* @__PURE__ */ u("div", { ref: xe }) },
246
+ contentScrollMode: "contained",
246
247
  children: /* @__PURE__ */ u(te, {
247
248
  permissions: g,
248
249
  children: /* @__PURE__ */ u(n, {
@@ -1 +1 @@
1
- {"version":3,"file":"BackofficeLayoutPage.js","names":[],"sources":["../../../src/pages/BackofficeLayoutPage.tsx"],"sourcesContent":["import {\n useEffect,\n useMemo,\n type JSX,\n type ReactNode,\n useCallback,\n useContext,\n useState,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n commitMutation,\n usePreloadedQuery,\n type PreloadedQuery,\n} from 'react-relay';\nimport type {\n GraphQLTaggedNode,\n MutationParameters,\n OperationType,\n} from 'relay-runtime';\nimport RoutingContext from '@plumile/router/routing/RoutingContext.js';\nimport useLocation from '@plumile/router/routing/useLocation.js';\n\nimport { AdminShellLayout } from '@plumile/ui/admin/templates/admin_shell_layout/AdminShellLayout.js';\nimport { ToastProvider } from '@plumile/ui/atomic/molecules/toast/ToastProvider.js';\nimport { EnvironmentBadge } from '@plumile/ui/backoffice/atoms/environment_badge/EnvironmentBadge.js';\nimport { GlobalSearchInput } from '@plumile/ui/backoffice/molecules/global_search_input/GlobalSearchInput.js';\nimport { BackofficeSidebarProfileMenu } from '@plumile/ui/backoffice/molecules/sidebar_profile_menu/BackofficeSidebarProfileMenu.js';\n\nimport { useBackofficeReactTranslation } from '../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeConfig } from '../provider/BackofficeConfigContext.js';\nimport type { LogoutResponse, LogoutVariables } from '../hooks/useAuth.js';\nimport { useBackofficeSidebarPins } from '../hooks/useBackofficeSidebarPins.js';\nimport { useSidebarGroupCollapse } from '../hooks/useSidebarGroupCollapse.js';\nimport { buildSidebarSections } from '../components/backoffice/layout/buildSidebarSections.js';\nimport { BackofficeContentBoundary } from '../components/backoffice/routing/BackofficeContentBoundary.js';\nimport {\n resolveActiveEntityId,\n resolveSidebarGroups,\n resolveVisibleEntityIds,\n} from '../components/backoffice/layout/sidebarUtils.js';\nimport { BackofficeTopbarPortalContextProvider } from '../components/backoffice/layout/breadcrumb/BackofficeTopbarPortalContext.js';\nimport { BackofficePermissionsProvider } from '../components/backoffice/layout/BackofficePermissionsContext.js';\nimport {\n mapViewerToSidebarProfileView,\n type BackofficeViewerIdentity,\n} from '../components/backoffice/layout/mapViewerToSidebarProfileView.js';\nimport { resetRelayStore } from '../relay/environment.js';\nimport { useRelayEnvironment } from '../relay/useRelayEnvironment.js';\nimport { getBackofficeLoginPath } from '../router/backofficeAuthPaths.js';\nimport type { BackofficeSidebarRecentItem } from '../provider/types.js';\n\nexport type BackofficeLayoutPageProps = {\n children: ReactNode;\n permissionsQuery?: GraphQLTaggedNode;\n prepared?: PreloadedQuery<OperationType> | null;\n authStatus?: {\n isLoggedIn?: boolean | null;\n me?: BackofficeViewerIdentity | null;\n } | null;\n activeGroupId?: string | null;\n};\n\ntype LayoutShellProps = {\n children: ReactNode;\n permissions: unknown;\n authStatus?: {\n isLoggedIn?: boolean | null;\n me?: BackofficeViewerIdentity | null;\n } | null;\n activeGroupId?: string | null;\n};\n\nconst DEFAULT_RECENT_ITEMS_STORAGE_KEY = 'plumile:backoffice:recent-items';\nconst DEFAULT_SIDEBAR_PREFS_STORAGE_KEY = 'plumile:backoffice:sidebar';\n\nconst readRecentItems = (\n storageKey: string,\n): readonly BackofficeSidebarRecentItem[] => {\n if (typeof window === 'undefined') {\n return [];\n }\n try {\n const raw = window.localStorage.getItem(storageKey);\n if (raw == null) {\n return [];\n }\n const parsed = JSON.parse(raw) as unknown;\n if (!Array.isArray(parsed)) {\n return [];\n }\n return parsed.filter((item): item is BackofficeSidebarRecentItem => {\n if (item == null || typeof item !== 'object') {\n return false;\n }\n const candidate = item as Partial<BackofficeSidebarRecentItem>;\n return (\n (candidate.kind === 'entity' || candidate.kind === 'tool') &&\n typeof candidate.id === 'string' &&\n typeof candidate.label === 'string' &&\n typeof candidate.href === 'string' &&\n typeof candidate.visitedAt === 'number'\n );\n });\n } catch {\n return [];\n }\n};\n\nconst writeRecentItems = (\n storageKey: string,\n items: readonly BackofficeSidebarRecentItem[],\n): void => {\n if (typeof window === 'undefined') {\n return;\n }\n try {\n window.localStorage.setItem(storageKey, JSON.stringify(items));\n } catch {\n // Ignore storage quota / privacy mode failures.\n }\n};\n\nconst BackofficeLayoutShell = ({\n children,\n permissions,\n authStatus,\n activeGroupId,\n}: LayoutShellProps): JSX.Element => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const { pathname } = useLocation();\n const routing = useContext(RoutingContext);\n const relayEnvironment = useRelayEnvironment();\n const {\n auth: authConfig,\n basePath,\n entities,\n sidebar,\n } = useBackofficeConfig();\n const [sidebarQuery, setSidebarQuery] = useState('');\n const sidebarPreferencesStorageKey =\n sidebar?.preferences?.storageKey ?? DEFAULT_SIDEBAR_PREFS_STORAGE_KEY;\n const persistSidebarCollapsed =\n sidebar?.preferences?.persistCollapsed === true;\n const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(() => {\n if (!persistSidebarCollapsed || typeof window === 'undefined') {\n return false;\n }\n try {\n return (\n window.localStorage.getItem(\n `${sidebarPreferencesStorageKey}:collapsed`,\n ) === 'true'\n );\n } catch {\n return false;\n }\n });\n const [isSigningOut, setIsSigningOut] = useState(false);\n const [topbarTarget, setTopbarTarget] = useState<HTMLDivElement | null>(null);\n const recentItemsConfig = sidebar?.recentItems;\n const recentItemsEnabled = recentItemsConfig?.enabled === true;\n const recentItemsStorageKey =\n recentItemsConfig?.storageKey ?? DEFAULT_RECENT_ITEMS_STORAGE_KEY;\n const recentItemsMaxItems = recentItemsConfig?.maxItems ?? 8;\n const [recentItems, setRecentItems] = useState<\n readonly BackofficeSidebarRecentItem[]\n >(() => {\n if (!recentItemsEnabled) {\n return [];\n }\n return readRecentItems(recentItemsStorageKey);\n });\n\n useEffect(() => {\n if (!persistSidebarCollapsed || typeof window === 'undefined') {\n return;\n }\n try {\n window.localStorage.setItem(\n `${sidebarPreferencesStorageKey}:collapsed`,\n String(isSidebarCollapsed),\n );\n } catch {\n // Ignore storage quota / privacy mode failures.\n }\n }, [\n isSidebarCollapsed,\n persistSidebarCollapsed,\n sidebarPreferencesStorageKey,\n ]);\n\n const groups = useMemo(() => {\n return resolveSidebarGroups(entities, sidebar);\n }, [entities, sidebar]);\n\n const groupIds = useMemo(() => {\n return Object.keys(groups);\n }, [groups]);\n\n const defaultCollapsedByGroupId = useMemo(() => {\n return Object.fromEntries(\n Object.entries(groups).map(([groupId, group]) => {\n return [groupId, group.behavior?.defaultCollapsed ?? true];\n }),\n );\n }, [groups]);\n\n const visibleEntityIds = useMemo(() => {\n return resolveVisibleEntityIds(groups, entities, sidebar, permissions);\n }, [entities, groups, permissions, sidebar]);\n\n const activeEntityId = useMemo(() => {\n return resolveActiveEntityId(pathname, entities);\n }, [entities, pathname]);\n\n useEffect(() => {\n if (!recentItemsEnabled || activeEntityId == null) {\n return;\n }\n const config = entities[activeEntityId];\n if (config == null) {\n return;\n }\n if (config.kind !== 'tool' && !config.hasList) {\n return;\n }\n const href = config.routes.list;\n let kind: BackofficeSidebarRecentItem['kind'] = 'entity';\n if (config.kind === 'tool') {\n kind = 'tool';\n }\n const item: BackofficeSidebarRecentItem = {\n kind,\n id: activeEntityId,\n label: config.label(tApp),\n href,\n visitedAt: Date.now(),\n };\n setRecentItems((prev) => {\n const next = [\n item,\n ...prev.filter((entry) => {\n return entry.id !== item.id || entry.kind !== item.kind;\n }),\n ].slice(0, recentItemsMaxItems);\n writeRecentItems(recentItemsStorageKey, next);\n return next;\n });\n }, [\n activeEntityId,\n entities,\n recentItemsEnabled,\n recentItemsMaxItems,\n recentItemsStorageKey,\n tApp,\n ]);\n\n const {\n pins,\n toggle: togglePin,\n reorder: reorderPin,\n } = useBackofficeSidebarPins({\n enabled: sidebar?.pinnedItems?.enabled === true,\n storageKey: sidebar?.pinnedItems?.storageKey,\n visibleEntityIds,\n });\n\n let groupCollapseStorageKey: string | undefined;\n if (sidebar?.preferences?.storageKey != null) {\n groupCollapseStorageKey = `${sidebar.preferences.storageKey}:groups`;\n }\n\n const { collapsedByGroupId, setCollapsed } = useSidebarGroupCollapse({\n groupIds,\n activeGroupId,\n defaultCollapsedByGroupId,\n persist: sidebar?.preferences?.persistGroups === true,\n storageKey: groupCollapseStorageKey,\n });\n\n const sections = useMemo(() => {\n return buildSidebarSections({\n basePath,\n pathname,\n entities,\n sidebar,\n permissions,\n searchQuery: sidebarQuery,\n tApp,\n t,\n pinnedEntityIds: pins,\n recentItems,\n onTogglePin: togglePin,\n onReorderPin: reorderPin,\n collapsedByGroupId,\n onGroupCollapsedChange: setCollapsed,\n sidebarCollapsed: false,\n });\n }, [\n basePath,\n collapsedByGroupId,\n entities,\n pathname,\n permissions,\n pins,\n recentItems,\n reorderPin,\n setCollapsed,\n sidebar,\n sidebarQuery,\n t,\n tApp,\n togglePin,\n ]);\n\n const mobileSections = 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 recentItems,\n onTogglePin: togglePin,\n onReorderPin: reorderPin,\n collapsedByGroupId,\n onGroupCollapsedChange: setCollapsed,\n sidebarCollapsed: false,\n });\n }, [\n basePath,\n collapsedByGroupId,\n entities,\n pathname,\n permissions,\n pins,\n recentItems,\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={false}\n viewer={sidebarProfile}\n labels={{\n sectionTitle: t('sidebar.profile.title'),\n menuAriaLabel: t('sidebar.profile.menuAriaLabel'),\n signOut: t('sidebar.profile.actions.signOut'),\n }}\n onSignOut={handleSignOut}\n isSigningOut={isSigningOut}\n />\n );\n\n const mobileSidebarFooter = (\n <BackofficeSidebarProfileMenu\n collapsed={false}\n viewer={sidebarProfile}\n labels={{\n sectionTitle: t('sidebar.profile.title'),\n menuAriaLabel: t('sidebar.profile.menuAriaLabel'),\n signOut: t('sidebar.profile.actions.signOut'),\n }}\n onSignOut={handleSignOut}\n isSigningOut={isSigningOut}\n />\n );\n\n let contentNode: JSX.Element | null = null;\n if (topbarTarget != null) {\n contentNode = (\n <BackofficeContentBoundary>{children}</BackofficeContentBoundary>\n );\n }\n\n const sidebarSearchNode = (\n <GlobalSearchInput\n value={sidebarQuery}\n onChange={setSidebarQuery}\n placeholder={t('sidebar.search.placeholder')}\n ariaLabel={t('sidebar.search.placeholder')}\n />\n );\n\n return (\n <ToastProvider>\n <AdminShellLayout\n sidebar={{\n sections,\n header: <EnvironmentBadge environment={environment} />,\n search: sidebarSearchNode,\n footer: sidebarFooter,\n isCollapsed: isSidebarCollapsed,\n onCollapsedChange: setIsSidebarCollapsed,\n collapseToggleLabel: t('sidebar.actions.collapseSidebar'),\n expandToggleLabel: t('sidebar.actions.expandSidebar'),\n navigationAriaLabel: t('sidebar.navigationAriaLabel'),\n }}\n mobileSidebar={{\n sections: mobileSections,\n header: <EnvironmentBadge environment={environment} />,\n search: sidebarSearchNode,\n footer: mobileSidebarFooter,\n isCollapsed: false,\n hideCollapseToggle: true,\n navigationAriaLabel: t('sidebar.navigationAriaLabel'),\n }}\n topbar={{\n breadcrumb: <div ref={setTopbarTarget} />,\n }}\n >\n <BackofficePermissionsProvider permissions={permissions}>\n <BackofficeTopbarPortalContextProvider\n value={{\n target: topbarTarget,\n dashboardHref: basePath,\n dashboardLabel: t('sidebar.items.dashboard'),\n }}\n >\n {contentNode}\n </BackofficeTopbarPortalContextProvider>\n </BackofficePermissionsProvider>\n </AdminShellLayout>\n </ToastProvider>\n );\n};\n\ntype LayoutWithPermissionsProps = {\n children: ReactNode;\n permissionsQuery: GraphQLTaggedNode;\n prepared: PreloadedQuery<OperationType>;\n authStatus?: {\n isLoggedIn?: boolean | null;\n me?: BackofficeViewerIdentity | null;\n } | null;\n activeGroupId?: string | null;\n};\n\nconst LayoutWithPermissions = ({\n children,\n permissionsQuery,\n prepared,\n authStatus,\n activeGroupId,\n}: LayoutWithPermissionsProps): JSX.Element => {\n const permissions = usePreloadedQuery(permissionsQuery, prepared);\n\n return (\n <BackofficeLayoutShell\n permissions={permissions}\n authStatus={authStatus}\n activeGroupId={activeGroupId}\n >\n {children}\n </BackofficeLayoutShell>\n );\n};\n\nexport const BackofficeLayoutPage = ({\n children,\n permissionsQuery,\n prepared,\n authStatus,\n activeGroupId,\n}: BackofficeLayoutPageProps): JSX.Element => {\n if (permissionsQuery != null && prepared != null) {\n return (\n <LayoutWithPermissions\n permissionsQuery={permissionsQuery}\n prepared={prepared}\n authStatus={authStatus}\n activeGroupId={activeGroupId}\n >\n {children}\n </LayoutWithPermissions>\n );\n }\n\n return (\n <BackofficeLayoutShell\n permissions={null}\n authStatus={authStatus}\n activeGroupId={activeGroupId}\n >\n {children}\n </BackofficeLayoutShell>\n );\n};\n\nexport default BackofficeLayoutPage;\n"],"mappings":"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"}
1
+ {"version":3,"file":"BackofficeLayoutPage.js","names":[],"sources":["../../../src/pages/BackofficeLayoutPage.tsx"],"sourcesContent":["import {\n useEffect,\n useMemo,\n type JSX,\n type ReactNode,\n useCallback,\n useContext,\n useState,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n commitMutation,\n usePreloadedQuery,\n type PreloadedQuery,\n} from 'react-relay';\nimport type {\n GraphQLTaggedNode,\n MutationParameters,\n OperationType,\n} from 'relay-runtime';\nimport RoutingContext from '@plumile/router/routing/RoutingContext.js';\nimport useLocation from '@plumile/router/routing/useLocation.js';\n\nimport { AdminShellLayout } from '@plumile/ui/admin/templates/admin_shell_layout/AdminShellLayout.js';\nimport { ToastProvider } from '@plumile/ui/atomic/molecules/toast/ToastProvider.js';\nimport { EnvironmentBadge } from '@plumile/ui/backoffice/atoms/environment_badge/EnvironmentBadge.js';\nimport { GlobalSearchInput } from '@plumile/ui/backoffice/molecules/global_search_input/GlobalSearchInput.js';\nimport { BackofficeSidebarProfileMenu } from '@plumile/ui/backoffice/molecules/sidebar_profile_menu/BackofficeSidebarProfileMenu.js';\n\nimport { useBackofficeReactTranslation } from '../i18n/useBackofficeReactTranslation.js';\nimport { useBackofficeConfig } from '../provider/BackofficeConfigContext.js';\nimport type { LogoutResponse, LogoutVariables } from '../hooks/useAuth.js';\nimport { useBackofficeSidebarPins } from '../hooks/useBackofficeSidebarPins.js';\nimport { useSidebarGroupCollapse } from '../hooks/useSidebarGroupCollapse.js';\nimport { buildSidebarSections } from '../components/backoffice/layout/buildSidebarSections.js';\nimport { BackofficeContentBoundary } from '../components/backoffice/routing/BackofficeContentBoundary.js';\nimport {\n resolveActiveEntityId,\n resolveSidebarGroups,\n resolveVisibleEntityIds,\n} from '../components/backoffice/layout/sidebarUtils.js';\nimport { BackofficeTopbarPortalContextProvider } from '../components/backoffice/layout/breadcrumb/BackofficeTopbarPortalContext.js';\nimport { BackofficePermissionsProvider } from '../components/backoffice/layout/BackofficePermissionsContext.js';\nimport {\n mapViewerToSidebarProfileView,\n type BackofficeViewerIdentity,\n} from '../components/backoffice/layout/mapViewerToSidebarProfileView.js';\nimport { resetRelayStore } from '../relay/environment.js';\nimport { useRelayEnvironment } from '../relay/useRelayEnvironment.js';\nimport { getBackofficeLoginPath } from '../router/backofficeAuthPaths.js';\nimport type { BackofficeSidebarRecentItem } from '../provider/types.js';\n\nexport type BackofficeLayoutPageProps = {\n children: ReactNode;\n permissionsQuery?: GraphQLTaggedNode;\n prepared?: PreloadedQuery<OperationType> | null;\n authStatus?: {\n isLoggedIn?: boolean | null;\n me?: BackofficeViewerIdentity | null;\n } | null;\n activeGroupId?: string | null;\n};\n\ntype LayoutShellProps = {\n children: ReactNode;\n permissions: unknown;\n authStatus?: {\n isLoggedIn?: boolean | null;\n me?: BackofficeViewerIdentity | null;\n } | null;\n activeGroupId?: string | null;\n};\n\nconst DEFAULT_RECENT_ITEMS_STORAGE_KEY = 'plumile:backoffice:recent-items';\nconst DEFAULT_SIDEBAR_PREFS_STORAGE_KEY = 'plumile:backoffice:sidebar';\n\nconst readRecentItems = (\n storageKey: string,\n): readonly BackofficeSidebarRecentItem[] => {\n if (typeof window === 'undefined') {\n return [];\n }\n try {\n const raw = window.localStorage.getItem(storageKey);\n if (raw == null) {\n return [];\n }\n const parsed = JSON.parse(raw) as unknown;\n if (!Array.isArray(parsed)) {\n return [];\n }\n return parsed.filter((item): item is BackofficeSidebarRecentItem => {\n if (item == null || typeof item !== 'object') {\n return false;\n }\n const candidate = item as Partial<BackofficeSidebarRecentItem>;\n return (\n (candidate.kind === 'entity' || candidate.kind === 'tool') &&\n typeof candidate.id === 'string' &&\n typeof candidate.label === 'string' &&\n typeof candidate.href === 'string' &&\n typeof candidate.visitedAt === 'number'\n );\n });\n } catch {\n return [];\n }\n};\n\nconst writeRecentItems = (\n storageKey: string,\n items: readonly BackofficeSidebarRecentItem[],\n): void => {\n if (typeof window === 'undefined') {\n return;\n }\n try {\n window.localStorage.setItem(storageKey, JSON.stringify(items));\n } catch {\n // Ignore storage quota / privacy mode failures.\n }\n};\n\nconst BackofficeLayoutShell = ({\n children,\n permissions,\n authStatus,\n activeGroupId,\n}: LayoutShellProps): JSX.Element => {\n const { t: tApp } = useTranslation();\n const { t } = useBackofficeReactTranslation();\n const { pathname } = useLocation();\n const routing = useContext(RoutingContext);\n const relayEnvironment = useRelayEnvironment();\n const {\n auth: authConfig,\n basePath,\n entities,\n sidebar,\n } = useBackofficeConfig();\n const [sidebarQuery, setSidebarQuery] = useState('');\n const sidebarPreferencesStorageKey =\n sidebar?.preferences?.storageKey ?? DEFAULT_SIDEBAR_PREFS_STORAGE_KEY;\n const persistSidebarCollapsed =\n sidebar?.preferences?.persistCollapsed === true;\n const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(() => {\n if (!persistSidebarCollapsed || typeof window === 'undefined') {\n return false;\n }\n try {\n return (\n window.localStorage.getItem(\n `${sidebarPreferencesStorageKey}:collapsed`,\n ) === 'true'\n );\n } catch {\n return false;\n }\n });\n const [isSigningOut, setIsSigningOut] = useState(false);\n const [topbarTarget, setTopbarTarget] = useState<HTMLDivElement | null>(null);\n const recentItemsConfig = sidebar?.recentItems;\n const recentItemsEnabled = recentItemsConfig?.enabled === true;\n const recentItemsStorageKey =\n recentItemsConfig?.storageKey ?? DEFAULT_RECENT_ITEMS_STORAGE_KEY;\n const recentItemsMaxItems = recentItemsConfig?.maxItems ?? 8;\n const [recentItems, setRecentItems] = useState<\n readonly BackofficeSidebarRecentItem[]\n >(() => {\n if (!recentItemsEnabled) {\n return [];\n }\n return readRecentItems(recentItemsStorageKey);\n });\n\n useEffect(() => {\n if (!persistSidebarCollapsed || typeof window === 'undefined') {\n return;\n }\n try {\n window.localStorage.setItem(\n `${sidebarPreferencesStorageKey}:collapsed`,\n String(isSidebarCollapsed),\n );\n } catch {\n // Ignore storage quota / privacy mode failures.\n }\n }, [\n isSidebarCollapsed,\n persistSidebarCollapsed,\n sidebarPreferencesStorageKey,\n ]);\n\n const groups = useMemo(() => {\n return resolveSidebarGroups(entities, sidebar);\n }, [entities, sidebar]);\n\n const groupIds = useMemo(() => {\n return Object.keys(groups);\n }, [groups]);\n\n const defaultCollapsedByGroupId = useMemo(() => {\n return Object.fromEntries(\n Object.entries(groups).map(([groupId, group]) => {\n return [groupId, group.behavior?.defaultCollapsed ?? true];\n }),\n );\n }, [groups]);\n\n const visibleEntityIds = useMemo(() => {\n return resolveVisibleEntityIds(groups, entities, sidebar, permissions);\n }, [entities, groups, permissions, sidebar]);\n\n const activeEntityId = useMemo(() => {\n return resolveActiveEntityId(pathname, entities);\n }, [entities, pathname]);\n\n useEffect(() => {\n if (!recentItemsEnabled || activeEntityId == null) {\n return;\n }\n const config = entities[activeEntityId];\n if (config == null) {\n return;\n }\n if (config.kind !== 'tool' && !config.hasList) {\n return;\n }\n const href = config.routes.list;\n let kind: BackofficeSidebarRecentItem['kind'] = 'entity';\n if (config.kind === 'tool') {\n kind = 'tool';\n }\n const item: BackofficeSidebarRecentItem = {\n kind,\n id: activeEntityId,\n label: config.label(tApp),\n href,\n visitedAt: Date.now(),\n };\n setRecentItems((prev) => {\n const next = [\n item,\n ...prev.filter((entry) => {\n return entry.id !== item.id || entry.kind !== item.kind;\n }),\n ].slice(0, recentItemsMaxItems);\n writeRecentItems(recentItemsStorageKey, next);\n return next;\n });\n }, [\n activeEntityId,\n entities,\n recentItemsEnabled,\n recentItemsMaxItems,\n recentItemsStorageKey,\n tApp,\n ]);\n\n const {\n pins,\n toggle: togglePin,\n reorder: reorderPin,\n } = useBackofficeSidebarPins({\n enabled: sidebar?.pinnedItems?.enabled === true,\n storageKey: sidebar?.pinnedItems?.storageKey,\n visibleEntityIds,\n });\n\n let groupCollapseStorageKey: string | undefined;\n if (sidebar?.preferences?.storageKey != null) {\n groupCollapseStorageKey = `${sidebar.preferences.storageKey}:groups`;\n }\n\n const { collapsedByGroupId, setCollapsed } = useSidebarGroupCollapse({\n groupIds,\n activeGroupId,\n defaultCollapsedByGroupId,\n persist: sidebar?.preferences?.persistGroups === true,\n storageKey: groupCollapseStorageKey,\n });\n\n const sections = useMemo(() => {\n return buildSidebarSections({\n basePath,\n pathname,\n entities,\n sidebar,\n permissions,\n searchQuery: sidebarQuery,\n tApp,\n t,\n pinnedEntityIds: pins,\n recentItems,\n onTogglePin: togglePin,\n onReorderPin: reorderPin,\n collapsedByGroupId,\n onGroupCollapsedChange: setCollapsed,\n sidebarCollapsed: false,\n });\n }, [\n basePath,\n collapsedByGroupId,\n entities,\n pathname,\n permissions,\n pins,\n recentItems,\n reorderPin,\n setCollapsed,\n sidebar,\n sidebarQuery,\n t,\n tApp,\n togglePin,\n ]);\n\n const mobileSections = 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 recentItems,\n onTogglePin: togglePin,\n onReorderPin: reorderPin,\n collapsedByGroupId,\n onGroupCollapsedChange: setCollapsed,\n sidebarCollapsed: false,\n });\n }, [\n basePath,\n collapsedByGroupId,\n entities,\n pathname,\n permissions,\n pins,\n recentItems,\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={false}\n viewer={sidebarProfile}\n labels={{\n sectionTitle: t('sidebar.profile.title'),\n menuAriaLabel: t('sidebar.profile.menuAriaLabel'),\n signOut: t('sidebar.profile.actions.signOut'),\n }}\n onSignOut={handleSignOut}\n isSigningOut={isSigningOut}\n />\n );\n\n const mobileSidebarFooter = (\n <BackofficeSidebarProfileMenu\n collapsed={false}\n viewer={sidebarProfile}\n labels={{\n sectionTitle: t('sidebar.profile.title'),\n menuAriaLabel: t('sidebar.profile.menuAriaLabel'),\n signOut: t('sidebar.profile.actions.signOut'),\n }}\n onSignOut={handleSignOut}\n isSigningOut={isSigningOut}\n />\n );\n\n let contentNode: JSX.Element | null = null;\n if (topbarTarget != null) {\n contentNode = (\n <BackofficeContentBoundary>{children}</BackofficeContentBoundary>\n );\n }\n\n const sidebarSearchNode = (\n <GlobalSearchInput\n value={sidebarQuery}\n onChange={setSidebarQuery}\n placeholder={t('sidebar.search.placeholder')}\n ariaLabel={t('sidebar.search.placeholder')}\n />\n );\n\n return (\n <ToastProvider>\n <AdminShellLayout\n sidebar={{\n sections,\n header: <EnvironmentBadge environment={environment} />,\n search: sidebarSearchNode,\n footer: sidebarFooter,\n isCollapsed: isSidebarCollapsed,\n onCollapsedChange: setIsSidebarCollapsed,\n collapseToggleLabel: t('sidebar.actions.collapseSidebar'),\n expandToggleLabel: t('sidebar.actions.expandSidebar'),\n navigationAriaLabel: t('sidebar.navigationAriaLabel'),\n }}\n mobileSidebar={{\n sections: mobileSections,\n header: <EnvironmentBadge environment={environment} />,\n search: sidebarSearchNode,\n footer: mobileSidebarFooter,\n isCollapsed: false,\n hideCollapseToggle: true,\n navigationAriaLabel: t('sidebar.navigationAriaLabel'),\n }}\n topbar={{\n breadcrumb: <div ref={setTopbarTarget} />,\n }}\n contentScrollMode=\"contained\"\n >\n <BackofficePermissionsProvider permissions={permissions}>\n <BackofficeTopbarPortalContextProvider\n value={{\n target: topbarTarget,\n dashboardHref: basePath,\n dashboardLabel: t('sidebar.items.dashboard'),\n }}\n >\n {contentNode}\n </BackofficeTopbarPortalContextProvider>\n </BackofficePermissionsProvider>\n </AdminShellLayout>\n </ToastProvider>\n );\n};\n\ntype LayoutWithPermissionsProps = {\n children: ReactNode;\n permissionsQuery: GraphQLTaggedNode;\n prepared: PreloadedQuery<OperationType>;\n authStatus?: {\n isLoggedIn?: boolean | null;\n me?: BackofficeViewerIdentity | null;\n } | null;\n activeGroupId?: string | null;\n};\n\nconst LayoutWithPermissions = ({\n children,\n permissionsQuery,\n prepared,\n authStatus,\n activeGroupId,\n}: LayoutWithPermissionsProps): JSX.Element => {\n const permissions = usePreloadedQuery(permissionsQuery, prepared);\n\n return (\n <BackofficeLayoutShell\n permissions={permissions}\n authStatus={authStatus}\n activeGroupId={activeGroupId}\n >\n {children}\n </BackofficeLayoutShell>\n );\n};\n\nexport const BackofficeLayoutPage = ({\n children,\n permissionsQuery,\n prepared,\n authStatus,\n activeGroupId,\n}: BackofficeLayoutPageProps): JSX.Element => {\n if (permissionsQuery != null && prepared != null) {\n return (\n <LayoutWithPermissions\n permissionsQuery={permissionsQuery}\n prepared={prepared}\n authStatus={authStatus}\n activeGroupId={activeGroupId}\n >\n {children}\n </LayoutWithPermissions>\n );\n }\n\n return (\n <BackofficeLayoutShell\n permissions={null}\n authStatus={authStatus}\n activeGroupId={activeGroupId}\n >\n {children}\n </BackofficeLayoutShell>\n );\n};\n\nexport default BackofficeLayoutPage;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"BackofficeEntityListScaffold.d.ts","sourceRoot":"","sources":["../../../../../src/components/backoffice/scaffolds/BackofficeEntityListScaffold.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,GAAG,EACR,KAAK,SAAS,EAKf,MAAM,OAAO,CAAC;AAiBf,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,QAAQ,EACd,MAAM,gDAAgD,CAAC;AAUxD,OAAO,KAAK,EAEV,mBAAmB,EAEnB,wCAAwC,EAEzC,MAAM,mCAAmC,CAAC;AA+H3C,KAAK,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC5C,KAAK,WAAW,GAAG,MAAM,CAAC;AAE1B,KAAK,KAAK,CAAC,OAAO,IAAI;IACpB,MAAM,EAAE,wCAAwC,CAAC;IACjD,KAAK,EAAE,mBAAmB,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IACtD,SAAS,EAAE,CAAC,IAAI,EAAE,mBAAmB,CAAC,YAAY,EAAE,WAAW,CAAC,KAAK,IAAI,CAAC;IAC1E,MAAM,CAAC,EAAE;QACP,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,IAAI,EAAE,SAAS,OAAO,EAAE,CAAC;IACzB,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC5B,OAAO,EAAE,SAAS,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;IAC7C,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,WAAW,EAAE,OAAO,CAAC;IACrB,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IAC9B,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,4BAA4B,GAAI,OAAO,EAClD,OAAO,KAAK,CAAC,OAAO,CAAC,KACpB,GAAG,CAAC,OAAO,GAAG,IAq5BhB,CAAC;AAEF,eAAe,4BAA4B,CAAC"}
1
+ {"version":3,"file":"BackofficeEntityListScaffold.d.ts","sourceRoot":"","sources":["../../../../../src/components/backoffice/scaffolds/BackofficeEntityListScaffold.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,GAAG,EACR,KAAK,SAAS,EAKf,MAAM,OAAO,CAAC;AAiBf,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,QAAQ,EACd,MAAM,gDAAgD,CAAC;AAUxD,OAAO,KAAK,EAEV,mBAAmB,EAEnB,wCAAwC,EAEzC,MAAM,mCAAmC,CAAC;AAgI3C,KAAK,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC5C,KAAK,WAAW,GAAG,MAAM,CAAC;AAE1B,KAAK,KAAK,CAAC,OAAO,IAAI;IACpB,MAAM,EAAE,wCAAwC,CAAC;IACjD,KAAK,EAAE,mBAAmB,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IACtD,SAAS,EAAE,CAAC,IAAI,EAAE,mBAAmB,CAAC,YAAY,EAAE,WAAW,CAAC,KAAK,IAAI,CAAC;IAC1E,MAAM,CAAC,EAAE;QACP,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,IAAI,EAAE,SAAS,OAAO,EAAE,CAAC;IACzB,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC5B,OAAO,EAAE,SAAS,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;IAC7C,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,WAAW,EAAE,OAAO,CAAC;IACrB,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IAC9B,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,4BAA4B,GAAI,OAAO,EAClD,OAAO,KAAK,CAAC,OAAO,CAAC,KACpB,GAAG,CAAC,OAAO,GAAG,IA45BhB,CAAC;AAEF,eAAe,4BAA4B,CAAC"}
@@ -1,5 +1,6 @@
1
1
  export declare const controlsRow: string;
2
2
  export declare const filterInput: string;
3
3
  export declare const embeddedContainer: string;
4
+ export declare const tableHost: string;
4
5
  export declare const embeddedHeader: string;
5
6
  //# sourceMappingURL=backofficeEntityListScaffold.css.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"backofficeEntityListScaffold.css.d.ts","sourceRoot":"","sources":["../../../../../src/components/backoffice/scaffolds/backofficeEntityListScaffold.css.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,WAAW,QAKtB,CAAC;AAEH,eAAO,MAAM,WAAW,QAYtB,CAAC;AAEH,eAAO,MAAM,iBAAiB,QAI5B,CAAC;AAEH,eAAO,MAAM,cAAc,QAIzB,CAAC"}
1
+ {"version":3,"file":"backofficeEntityListScaffold.css.d.ts","sourceRoot":"","sources":["../../../../../src/components/backoffice/scaffolds/backofficeEntityListScaffold.css.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,WAAW,QAKtB,CAAC;AAEH,eAAO,MAAM,WAAW,QAYtB,CAAC;AAEH,eAAO,MAAM,iBAAiB,QAI5B,CAAC;AAEH,eAAO,MAAM,SAAS,QAKpB,CAAC;AAEH,eAAO,MAAM,cAAc,QAIzB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const BACKOFFICE_LIST_BODY_SCROLL_MODE: "contained";
2
+ //# sourceMappingURL=backofficeListScrollMode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backofficeListScrollMode.d.ts","sourceRoot":"","sources":["../../../../../src/components/backoffice/scaffolds/backofficeListScrollMode.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gCAAgC,EAAG,WAAoB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"BackofficeLayoutPage.d.ts","sourceRoot":"","sources":["../../../src/pages/BackofficeLayoutPage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,GAAG,EACR,KAAK,SAAS,EAIf,MAAM,OAAO,CAAC;AAEf,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EACV,iBAAiB,EAEjB,aAAa,EACd,MAAM,eAAe,CAAC;AAwBvB,OAAO,EAEL,KAAK,wBAAwB,EAC9B,MAAM,kEAAkE,CAAC;AAM1E,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,EAAE,SAAS,CAAC;IACpB,gBAAgB,CAAC,EAAE,iBAAiB,CAAC;IACrC,QAAQ,CAAC,EAAE,cAAc,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;IAChD,UAAU,CAAC,EAAE;QACX,UAAU,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;QAC5B,EAAE,CAAC,EAAE,wBAAwB,GAAG,IAAI,CAAC;KACtC,GAAG,IAAI,CAAC;IACT,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,CAAC;AAkdF,eAAO,MAAM,oBAAoB,GAAI,sEAMlC,yBAAyB,KAAG,GAAG,CAAC,OAuBlC,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
1
+ {"version":3,"file":"BackofficeLayoutPage.d.ts","sourceRoot":"","sources":["../../../src/pages/BackofficeLayoutPage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,GAAG,EACR,KAAK,SAAS,EAIf,MAAM,OAAO,CAAC;AAEf,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EACV,iBAAiB,EAEjB,aAAa,EACd,MAAM,eAAe,CAAC;AAwBvB,OAAO,EAEL,KAAK,wBAAwB,EAC9B,MAAM,kEAAkE,CAAC;AAM1E,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,EAAE,SAAS,CAAC;IACpB,gBAAgB,CAAC,EAAE,iBAAiB,CAAC;IACrC,QAAQ,CAAC,EAAE,cAAc,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;IAChD,UAAU,CAAC,EAAE;QACX,UAAU,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;QAC5B,EAAE,CAAC,EAAE,wBAAwB,GAAG,IAAI,CAAC;KACtC,GAAG,IAAI,CAAC;IACT,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,CAAC;AAmdF,eAAO,MAAM,oBAAoB,GAAI,sEAMlC,yBAAyB,KAAG,GAAG,CAAC,OAuBlC,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plumile/backoffice-react",
3
- "version": "0.1.114",
3
+ "version": "0.1.116",
4
4
  "description": "React provider and pages for Kronex backoffice",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -179,11 +179,11 @@
179
179
  "tslib": "^2.8.1"
180
180
  },
181
181
  "devDependencies": {
182
- "@plumile/auth": "^0.1.114",
183
- "@plumile/backoffice-core": "^0.1.114",
184
- "@plumile/filter-query": "^0.1.114",
185
- "@plumile/router": "^0.1.114",
186
- "@plumile/ui": "^0.1.114",
182
+ "@plumile/auth": "^0.1.116",
183
+ "@plumile/backoffice-core": "^0.1.116",
184
+ "@plumile/filter-query": "^0.1.116",
185
+ "@plumile/router": "^0.1.116",
186
+ "@plumile/ui": "^0.1.116",
187
187
  "@types/react": "19.2.14",
188
188
  "@types/react-dom": "19.2.3",
189
189
  "@types/relay-runtime": "20.1.1",