@12-apps/ui 6.24.4 → 6.24.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/_internal/components/data-display/CardKit/row-actions-to-menu.js +1 -1
  2. package/dist/_internal/components/data-display/DataViews/DataViewsGrid.js +5 -5
  3. package/dist/_internal/components/data-display/DataViews/DataViewsTableBase.js +6 -6
  4. package/dist/_internal/components/data-display/DataViews/data-views-category-pill.js +1 -1
  5. package/dist/_internal/components/data-display/DataViews/data-views-filter-panel.js +1 -1
  6. package/dist/_internal/components/data-display/DataViews/data-views-grid-parts.js +4 -4
  7. package/dist/_internal/components/data-display/DataViews/data-views-inline-bar.js +1 -1
  8. package/dist/_internal/components/data-display/DataViews/data-views-more-fields.js +1 -1
  9. package/dist/_internal/components/data-display/DataViews/data-views-more-filters.js +1 -1
  10. package/dist/_internal/components/data-display/DataViews/data-views-shell-toolbar.js +3 -3
  11. package/dist/_internal/components/data-display/DataViews/data-views-table-parts.js +1 -1
  12. package/dist/_internal/components/data-display/DataViews/data-views-toolbar.js +2 -2
  13. package/dist/_internal/components/index.js +1 -1
  14. package/dist/_internal/components/layout/ContentToolbar/ContentToolbar.js +1 -1
  15. package/dist/_internal/components/layout/index.js +1 -1
  16. package/dist/{chunk-JD4IVP22.js → chunk-4ZV7N5CU.js} +2 -2
  17. package/dist/{chunk-QX2PLXQA.js → chunk-53PDVLRK.js} +2 -2
  18. package/dist/{chunk-7GKRZJWI.js → chunk-EMMPNB6D.js} +2 -2
  19. package/dist/{chunk-TSPHRZ4U.js → chunk-L2E7TY7P.js} +76 -36
  20. package/dist/chunk-L2E7TY7P.js.map +1 -0
  21. package/dist/{chunk-NXNNICH7.js → chunk-LWRMKF7D.js} +2 -2
  22. package/dist/{chunk-5MXVT7DO.js → chunk-ZBXG6RVJ.js} +2 -2
  23. package/dist/chunk-ZBXG6RVJ.js.map +1 -0
  24. package/dist/{chunk-JPV45AD6.js → chunk-ZXOT3U6U.js} +2 -2
  25. package/dist/data-display/CardKit.js +1 -1
  26. package/dist/data-display/DataViews.js +6 -6
  27. package/dist/layout/ContentToolbar.js +1 -1
  28. package/dist/types/components/data-display/CardKit/row-actions-to-menu.d.ts +18 -2
  29. package/dist/types/components/data-display/CardKit/row-actions-to-menu.d.ts.map +1 -1
  30. package/dist/types/components/layout/ContentToolbar/ContentToolbar.d.ts.map +1 -1
  31. package/package.json +1 -1
  32. package/src/components/data-display/CardKit/row-actions-to-menu.ts +19 -2
  33. package/src/components/data-display/DataViews/RESPONSIVE-BEHAVIOUR.md +43 -0
  34. package/src/components/layout/ContentToolbar/ContentToolbar.tsx +82 -26
  35. package/dist/chunk-5MXVT7DO.js.map +0 -1
  36. package/dist/chunk-TSPHRZ4U.js.map +0 -1
  37. /package/dist/{chunk-JD4IVP22.js.map → chunk-4ZV7N5CU.js.map} +0 -0
  38. /package/dist/{chunk-QX2PLXQA.js.map → chunk-53PDVLRK.js.map} +0 -0
  39. /package/dist/{chunk-7GKRZJWI.js.map → chunk-EMMPNB6D.js.map} +0 -0
  40. /package/dist/{chunk-NXNNICH7.js.map → chunk-LWRMKF7D.js.map} +0 -0
  41. /package/dist/{chunk-JPV45AD6.js.map → chunk-ZXOT3U6U.js.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  rowActionsToMenuItems
3
- } from "../../../../chunk-5MXVT7DO.js";
3
+ } from "../../../../chunk-ZBXG6RVJ.js";
4
4
  import "../../../../chunk-PZ5AY32C.js";
5
5
  export {
6
6
  rowActionsToMenuItems
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import {
3
3
  DataViewsGrid
4
- } from "../../../../chunk-QX2PLXQA.js";
5
- import "../../../../chunk-NXNNICH7.js";
4
+ } from "../../../../chunk-53PDVLRK.js";
5
+ import "../../../../chunk-LWRMKF7D.js";
6
6
  import "../../../../chunk-BPLFM2GL.js";
7
7
  import "../../../../chunk-E55CJV65.js";
8
8
  import "../../../../chunk-PN5CQKA2.js";
@@ -21,14 +21,14 @@ import "../../../../chunk-CBOB5AV6.js";
21
21
  import "../../../../chunk-HP2ODXNA.js";
22
22
  import "../../../../chunk-TQ6FPOPD.js";
23
23
  import "../../../../chunk-IAGOUTI6.js";
24
- import "../../../../chunk-7GKRZJWI.js";
24
+ import "../../../../chunk-EMMPNB6D.js";
25
25
  import "../../../../chunk-KX75HM5U.js";
26
26
  import "../../../../chunk-XKV5ZIBG.js";
27
27
  import "../../../../chunk-A7Q5AQVD.js";
28
28
  import "../../../../chunk-OGGHD64H.js";
29
29
  import "../../../../chunk-CZPU5TW3.js";
30
30
  import "../../../../chunk-6VP2L3DJ.js";
31
- import "../../../../chunk-JD4IVP22.js";
31
+ import "../../../../chunk-4ZV7N5CU.js";
32
32
  import "../../../../chunk-SQNW22ZZ.js";
33
33
  import "../../../../chunk-7NSX7A5H.js";
34
34
  import "../../../../chunk-DW5FRWRQ.js";
@@ -59,7 +59,7 @@ import "../../../../chunk-7AIL2F5E.js";
59
59
  import "../../../../chunk-WVML3ENZ.js";
60
60
  import "../../../../chunk-IDHZHOZW.js";
61
61
  import "../../../../chunk-MOLQGQEQ.js";
62
- import "../../../../chunk-TSPHRZ4U.js";
62
+ import "../../../../chunk-L2E7TY7P.js";
63
63
  import "../../../../chunk-JMVIIKII.js";
64
64
  import "../../../../chunk-WXD7MGBT.js";
65
65
  import "../../../../chunk-WQFIV5WD.js";
@@ -1,11 +1,11 @@
1
1
  "use client";
2
2
  import {
3
3
  DataViewsTableBase
4
- } from "../../../../chunk-JPV45AD6.js";
4
+ } from "../../../../chunk-ZXOT3U6U.js";
5
5
  import "../../../../chunk-4X4KM4ZB.js";
6
- import "../../../../chunk-QX2PLXQA.js";
6
+ import "../../../../chunk-53PDVLRK.js";
7
7
  import "../../../../chunk-ZOLAYP2D.js";
8
- import "../../../../chunk-NXNNICH7.js";
8
+ import "../../../../chunk-LWRMKF7D.js";
9
9
  import "../../../../chunk-BPLFM2GL.js";
10
10
  import "../../../../chunk-E55CJV65.js";
11
11
  import "../../../../chunk-PN5CQKA2.js";
@@ -24,14 +24,14 @@ import "../../../../chunk-CBOB5AV6.js";
24
24
  import "../../../../chunk-HP2ODXNA.js";
25
25
  import "../../../../chunk-TQ6FPOPD.js";
26
26
  import "../../../../chunk-IAGOUTI6.js";
27
- import "../../../../chunk-7GKRZJWI.js";
27
+ import "../../../../chunk-EMMPNB6D.js";
28
28
  import "../../../../chunk-KX75HM5U.js";
29
29
  import "../../../../chunk-XKV5ZIBG.js";
30
30
  import "../../../../chunk-A7Q5AQVD.js";
31
31
  import "../../../../chunk-OGGHD64H.js";
32
32
  import "../../../../chunk-CZPU5TW3.js";
33
33
  import "../../../../chunk-6VP2L3DJ.js";
34
- import "../../../../chunk-JD4IVP22.js";
34
+ import "../../../../chunk-4ZV7N5CU.js";
35
35
  import "../../../../chunk-SQNW22ZZ.js";
36
36
  import "../../../../chunk-7NSX7A5H.js";
37
37
  import "../../../../chunk-DW5FRWRQ.js";
@@ -69,7 +69,7 @@ import "../../../../chunk-7AIL2F5E.js";
69
69
  import "../../../../chunk-WVML3ENZ.js";
70
70
  import "../../../../chunk-IDHZHOZW.js";
71
71
  import "../../../../chunk-MOLQGQEQ.js";
72
- import "../../../../chunk-TSPHRZ4U.js";
72
+ import "../../../../chunk-L2E7TY7P.js";
73
73
  import "../../../../chunk-JMVIIKII.js";
74
74
  import "../../../../chunk-WXD7MGBT.js";
75
75
  import "../../../../chunk-WQFIV5WD.js";
@@ -5,7 +5,7 @@ import {
5
5
  } from "../../../../chunk-EJQW2IYW.js";
6
6
  import "../../../../chunk-KHG57NAE.js";
7
7
  import "../../../../chunk-MOLQGQEQ.js";
8
- import "../../../../chunk-TSPHRZ4U.js";
8
+ import "../../../../chunk-L2E7TY7P.js";
9
9
  import "../../../../chunk-JMVIIKII.js";
10
10
  import "../../../../chunk-WXD7MGBT.js";
11
11
  import "../../../../chunk-WQFIV5WD.js";
@@ -14,7 +14,7 @@ import "../../../../chunk-4NS4PJJH.js";
14
14
  import "../../../../chunk-J3JGO6Y6.js";
15
15
  import "../../../../chunk-7AIL2F5E.js";
16
16
  import "../../../../chunk-MOLQGQEQ.js";
17
- import "../../../../chunk-TSPHRZ4U.js";
17
+ import "../../../../chunk-L2E7TY7P.js";
18
18
  import "../../../../chunk-JMVIIKII.js";
19
19
  import "../../../../chunk-WXD7MGBT.js";
20
20
  import "../../../../chunk-WQFIV5WD.js";
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  GridShell
4
- } from "../../../../chunk-NXNNICH7.js";
4
+ } from "../../../../chunk-LWRMKF7D.js";
5
5
  import "../../../../chunk-BPLFM2GL.js";
6
6
  import "../../../../chunk-E55CJV65.js";
7
7
  import "../../../../chunk-PN5CQKA2.js";
@@ -20,14 +20,14 @@ import "../../../../chunk-CBOB5AV6.js";
20
20
  import "../../../../chunk-HP2ODXNA.js";
21
21
  import "../../../../chunk-TQ6FPOPD.js";
22
22
  import "../../../../chunk-IAGOUTI6.js";
23
- import "../../../../chunk-7GKRZJWI.js";
23
+ import "../../../../chunk-EMMPNB6D.js";
24
24
  import "../../../../chunk-KX75HM5U.js";
25
25
  import "../../../../chunk-XKV5ZIBG.js";
26
26
  import "../../../../chunk-A7Q5AQVD.js";
27
27
  import "../../../../chunk-OGGHD64H.js";
28
28
  import "../../../../chunk-CZPU5TW3.js";
29
29
  import "../../../../chunk-6VP2L3DJ.js";
30
- import "../../../../chunk-JD4IVP22.js";
30
+ import "../../../../chunk-4ZV7N5CU.js";
31
31
  import "../../../../chunk-SQNW22ZZ.js";
32
32
  import "../../../../chunk-7NSX7A5H.js";
33
33
  import "../../../../chunk-DW5FRWRQ.js";
@@ -52,7 +52,7 @@ import "../../../../chunk-7AIL2F5E.js";
52
52
  import "../../../../chunk-WVML3ENZ.js";
53
53
  import "../../../../chunk-IDHZHOZW.js";
54
54
  import "../../../../chunk-MOLQGQEQ.js";
55
- import "../../../../chunk-TSPHRZ4U.js";
55
+ import "../../../../chunk-L2E7TY7P.js";
56
56
  import "../../../../chunk-JMVIIKII.js";
57
57
  import "../../../../chunk-WXD7MGBT.js";
58
58
  import "../../../../chunk-WQFIV5WD.js";
@@ -17,7 +17,7 @@ import "../../../../chunk-4NS4PJJH.js";
17
17
  import "../../../../chunk-J3JGO6Y6.js";
18
18
  import "../../../../chunk-7AIL2F5E.js";
19
19
  import "../../../../chunk-MOLQGQEQ.js";
20
- import "../../../../chunk-TSPHRZ4U.js";
20
+ import "../../../../chunk-L2E7TY7P.js";
21
21
  import "../../../../chunk-JMVIIKII.js";
22
22
  import "../../../../chunk-WXD7MGBT.js";
23
23
  import "../../../../chunk-WQFIV5WD.js";
@@ -13,7 +13,7 @@ import "../../../../chunk-4NS4PJJH.js";
13
13
  import "../../../../chunk-J3JGO6Y6.js";
14
14
  import "../../../../chunk-7AIL2F5E.js";
15
15
  import "../../../../chunk-MOLQGQEQ.js";
16
- import "../../../../chunk-TSPHRZ4U.js";
16
+ import "../../../../chunk-L2E7TY7P.js";
17
17
  import "../../../../chunk-JMVIIKII.js";
18
18
  import "../../../../chunk-WXD7MGBT.js";
19
19
  import "../../../../chunk-WQFIV5WD.js";
@@ -13,7 +13,7 @@ import "../../../../chunk-4NS4PJJH.js";
13
13
  import "../../../../chunk-J3JGO6Y6.js";
14
14
  import "../../../../chunk-7AIL2F5E.js";
15
15
  import "../../../../chunk-MOLQGQEQ.js";
16
- import "../../../../chunk-TSPHRZ4U.js";
16
+ import "../../../../chunk-L2E7TY7P.js";
17
17
  import "../../../../chunk-JMVIIKII.js";
18
18
  import "../../../../chunk-WXD7MGBT.js";
19
19
  import "../../../../chunk-WQFIV5WD.js";
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import {
3
3
  ShellToolbar
4
- } from "../../../../chunk-7GKRZJWI.js";
5
- import "../../../../chunk-JD4IVP22.js";
4
+ } from "../../../../chunk-EMMPNB6D.js";
5
+ import "../../../../chunk-4ZV7N5CU.js";
6
6
  import "../../../../chunk-SQNW22ZZ.js";
7
7
  import "../../../../chunk-7NSX7A5H.js";
8
8
  import "../../../../chunk-DW5FRWRQ.js";
@@ -16,7 +16,7 @@ import "../../../../chunk-KHG57NAE.js";
16
16
  import "../../../../chunk-WVML3ENZ.js";
17
17
  import "../../../../chunk-IDHZHOZW.js";
18
18
  import "../../../../chunk-MOLQGQEQ.js";
19
- import "../../../../chunk-TSPHRZ4U.js";
19
+ import "../../../../chunk-L2E7TY7P.js";
20
20
  import "../../../../chunk-JMVIIKII.js";
21
21
  import "../../../../chunk-WXD7MGBT.js";
22
22
  import "../../../../chunk-WQFIV5WD.js";
@@ -10,7 +10,7 @@ import "../../../../chunk-5M4TYFR3.js";
10
10
  import "../../../../chunk-2HPP6RVC.js";
11
11
  import "../../../../chunk-KHG57NAE.js";
12
12
  import "../../../../chunk-MOLQGQEQ.js";
13
- import "../../../../chunk-TSPHRZ4U.js";
13
+ import "../../../../chunk-L2E7TY7P.js";
14
14
  import "../../../../chunk-JMVIIKII.js";
15
15
  import "../../../../chunk-WXD7MGBT.js";
16
16
  import "../../../../chunk-WQFIV5WD.js";
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  GridToolbar
4
- } from "../../../../chunk-JD4IVP22.js";
4
+ } from "../../../../chunk-4ZV7N5CU.js";
5
5
  import "../../../../chunk-SQNW22ZZ.js";
6
6
  import "../../../../chunk-7NSX7A5H.js";
7
7
  import "../../../../chunk-DW5FRWRQ.js";
@@ -15,7 +15,7 @@ import "../../../../chunk-KHG57NAE.js";
15
15
  import "../../../../chunk-WVML3ENZ.js";
16
16
  import "../../../../chunk-IDHZHOZW.js";
17
17
  import "../../../../chunk-MOLQGQEQ.js";
18
- import "../../../../chunk-TSPHRZ4U.js";
18
+ import "../../../../chunk-L2E7TY7P.js";
19
19
  import "../../../../chunk-JMVIIKII.js";
20
20
  import "../../../../chunk-WXD7MGBT.js";
21
21
  import "../../../../chunk-WQFIV5WD.js";
@@ -537,7 +537,7 @@ import {
537
537
  import "../../chunk-MOLQGQEQ.js";
538
538
  import {
539
539
  ContentToolbar
540
- } from "../../chunk-TSPHRZ4U.js";
540
+ } from "../../chunk-L2E7TY7P.js";
541
541
  import {
542
542
  ColumnsMenu
543
543
  } from "../../chunk-JMVIIKII.js";
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  ContentToolbar
4
- } from "../../../../chunk-TSPHRZ4U.js";
4
+ } from "../../../../chunk-L2E7TY7P.js";
5
5
  import "../../../../chunk-PZ5AY32C.js";
6
6
  export {
7
7
  ContentToolbar
@@ -74,7 +74,7 @@ import {
74
74
  import "../../../chunk-MOLQGQEQ.js";
75
75
  import {
76
76
  ContentToolbar
77
- } from "../../../chunk-TSPHRZ4U.js";
77
+ } from "../../../chunk-L2E7TY7P.js";
78
78
  import {
79
79
  ColumnsMenu
80
80
  } from "../../../chunk-JMVIIKII.js";
@@ -12,7 +12,7 @@ import {
12
12
  } from "./chunk-KHG57NAE.js";
13
13
  import {
14
14
  ContentToolbar
15
- } from "./chunk-TSPHRZ4U.js";
15
+ } from "./chunk-L2E7TY7P.js";
16
16
  import {
17
17
  FilterTrigger
18
18
  } from "./chunk-LVCUJ7YU.js";
@@ -133,4 +133,4 @@ function GridToolbar(props) {
133
133
  export {
134
134
  GridToolbar
135
135
  };
136
- //# sourceMappingURL=chunk-JD4IVP22.js.map
136
+ //# sourceMappingURL=chunk-4ZV7N5CU.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  GridShell
3
- } from "./chunk-NXNNICH7.js";
3
+ } from "./chunk-LWRMKF7D.js";
4
4
  import {
5
5
  useDataViewsState
6
6
  } from "./chunk-TX5V42AY.js";
@@ -27,4 +27,4 @@ function DataViewsGrid(props) {
27
27
  export {
28
28
  DataViewsGrid
29
29
  };
30
- //# sourceMappingURL=chunk-QX2PLXQA.js.map
30
+ //# sourceMappingURL=chunk-53PDVLRK.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  GridToolbar
3
- } from "./chunk-JD4IVP22.js";
3
+ } from "./chunk-4ZV7N5CU.js";
4
4
 
5
5
  // src/components/data-display/DataViews/data-views-shell-toolbar.tsx
6
6
  import { jsx } from "react/jsx-runtime";
@@ -64,4 +64,4 @@ function ShellToolbar({
64
64
  export {
65
65
  ShellToolbar
66
66
  };
67
- //# sourceMappingURL=chunk-7GKRZJWI.js.map
67
+ //# sourceMappingURL=chunk-EMMPNB6D.js.map
@@ -37,11 +37,24 @@ function SelectionCluster({
37
37
  sx: {
38
38
  display: "flex",
39
39
  minWidth: 0,
40
- // Mobile: don't grow, so the controls sit on the SAME line as the checkbox
41
- // (no orphaned selection row). Desktop: grow to push controls right.
42
- flex: { xs: "0 0 auto", md: 1 },
40
+ // Browsing (mobile): don't grow, so the controls sit on the SAME line as
41
+ // the checkbox (no orphaned selection row). Desktop: grow to push
42
+ // controls right.
43
+ //
44
+ // SELECTING (mobile) it must be able to shrink instead. Its children are
45
+ // all `flex-shrink: 0`, so a cluster pinned at content width cannot wrap
46
+ // and the row painted past the toolbar's own edge — on Produtos at 390px
47
+ // that took "Ações" off-screen behind a sideways scroll, which is the
48
+ // one control the selection exists to reach.
49
+ flex: { xs: hasSelection ? "1 1 auto" : "0 0 auto", md: 1 },
43
50
  alignItems: "center",
44
- gap: 1.5,
51
+ // Wrapping is the phone's answer, and only the phone's: below `md` the
52
+ // cluster carries the count, the scope control and "Ações" at once, and
53
+ // no combination of those fits 320px on one line. From `md` up it stays
54
+ // a single line, where it always fitted.
55
+ flexWrap: { xs: "wrap", md: "nowrap" },
56
+ columnGap: 1.5,
57
+ rowGap: 1,
45
58
  ml: edgeAlign ? -1.5 : 0
46
59
  },
47
60
  children: [
@@ -68,41 +81,68 @@ function SelectionCluster({
68
81
  sx: { p: 0.5, display: { xs: "inline-flex", md: "none" } }
69
82
  }
70
83
  ),
71
- hasSelection ? /* @__PURE__ */ jsxs(Fragment, { children: [
72
- /* @__PURE__ */ jsx(
73
- Button,
74
- {
75
- variant: "text",
76
- size: "small",
77
- color: "inherit",
78
- onClick: clearSelection,
79
- "data-testid": clearAllTestId,
80
- sx: selectionButtonSx,
81
- children: clearAllText
82
- }
83
- ),
84
- /* @__PURE__ */ jsx(Divider, { orientation: "vertical", flexItem: true, sx: { height: 16, alignSelf: "center" } }),
85
- /* @__PURE__ */ jsxs(
86
- Typography,
87
- {
88
- component: "span",
89
- "data-testid": "selected-count-indicator",
90
- sx: { fontSize: "0.875rem", color: "text.secondary", whiteSpace: "nowrap", flexShrink: 0 },
91
- children: [
92
- selectedCount,
93
- " ",
94
- selectedCount === 1 ? "item" : "items",
95
- " selected"
96
- ]
97
- }
98
- ),
99
- selectionExtra,
100
- actionsSlot
101
- ] }) : actionsSlot
84
+ hasSelection ? /* @__PURE__ */ jsx(
85
+ SelectionState,
86
+ {
87
+ selectedCount,
88
+ clearSelection,
89
+ clearAllTestId,
90
+ clearAllText,
91
+ selectionExtra
92
+ }
93
+ ) : null,
94
+ actionsSlot
102
95
  ]
103
96
  }
104
97
  );
105
98
  }
99
+ function SelectionState({
100
+ selectedCount,
101
+ clearSelection,
102
+ clearAllTestId,
103
+ clearAllText,
104
+ selectionExtra
105
+ }) {
106
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
107
+ /* @__PURE__ */ jsx(
108
+ Button,
109
+ {
110
+ variant: "text",
111
+ size: "small",
112
+ color: "inherit",
113
+ onClick: clearSelection,
114
+ "data-testid": clearAllTestId,
115
+ sx: selectionButtonSx,
116
+ children: clearAllText
117
+ }
118
+ ),
119
+ /* @__PURE__ */ jsx(Divider, { orientation: "vertical", flexItem: true, sx: { height: 16, alignSelf: "center" } }),
120
+ /* @__PURE__ */ jsxs(
121
+ Typography,
122
+ {
123
+ component: "span",
124
+ "data-testid": "selected-count-indicator",
125
+ sx: { fontSize: "0.875rem", color: "text.secondary", whiteSpace: "nowrap", flexShrink: 0 },
126
+ children: [
127
+ selectedCount,
128
+ " ",
129
+ selectedCount === 1 ? "item" : "items",
130
+ " selected"
131
+ ]
132
+ }
133
+ ),
134
+ selectionExtra !== void 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
135
+ /* @__PURE__ */ jsx(
136
+ Box,
137
+ {
138
+ "aria-hidden": true,
139
+ sx: { flexBasis: "100%", height: 0, display: { xs: "block", md: "none" } }
140
+ }
141
+ ),
142
+ selectionExtra
143
+ ] })
144
+ ] });
145
+ }
106
146
  function BrowsingClusters({
107
147
  leadingControls,
108
148
  rightControls,
@@ -226,4 +266,4 @@ function ContentToolbar({
226
266
  export {
227
267
  ContentToolbar
228
268
  };
229
- //# sourceMappingURL=chunk-TSPHRZ4U.js.map
269
+ //# sourceMappingURL=chunk-L2E7TY7P.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/layout/ContentToolbar/ContentToolbar.tsx"],"sourcesContent":["'use client';\n\nimport Box from '@mui/material/Box/index.js';\nimport Button from '@mui/material/Button/index.js';\nimport Checkbox from '@mui/material/Checkbox/index.js';\nimport Divider from '@mui/material/Divider/index.js';\nimport Typography from '@mui/material/Typography/index.js';\nimport React from 'react';\n\nimport type { ContentToolbarProps } from './ContentToolbar.types';\n\nconst selectionButtonSx = {\n minWidth: 0,\n height: 'auto',\n borderRadius: 0.5,\n fontWeight: 600,\n py: 0.5,\n px: 1.5,\n fontSize: '0.75rem',\n textTransform: 'none',\n color: 'text.primary',\n} as const;\n\ntype SelectionClusterProps = Pick<\n ContentToolbarProps,\n | 'hasSelection'\n | 'selectedCount'\n | 'selectAll'\n | 'clearSelection'\n | 'actions'\n | 'selectionExtra'\n | 'selectAllTestId'\n | 'clearAllTestId'\n | 'edgeAlign'\n | 'selectAllLabel'\n | 'selectAllText'\n | 'clearAllText'\n>;\n\n/** The left cluster: Select All + (when selecting) Clear All / count / actions. */\nfunction SelectionCluster({\n hasSelection,\n selectedCount,\n selectAll,\n clearSelection,\n actions,\n selectionExtra,\n selectAllTestId,\n clearAllTestId,\n edgeAlign = false,\n selectAllLabel,\n selectAllText,\n clearAllText,\n}: SelectionClusterProps): React.JSX.Element {\n const actionsSlot = actions !== undefined && (\n <Box sx={{ ml: 0.5, display: 'flex', flexShrink: 0, alignItems: 'center' }}>{actions}</Box>\n );\n return (\n <Box\n sx={{\n display: 'flex',\n minWidth: 0,\n // Browsing (mobile): don't grow, so the controls sit on the SAME line as\n // the checkbox (no orphaned selection row). Desktop: grow to push\n // controls right.\n //\n // SELECTING (mobile) it must be able to shrink instead. Its children are\n // all `flex-shrink: 0`, so a cluster pinned at content width cannot wrap\n // and the row painted past the toolbar's own edge — on Produtos at 390px\n // that took \"Ações\" off-screen behind a sideways scroll, which is the\n // one control the selection exists to reach.\n flex: { xs: hasSelection ? '1 1 auto' : '0 0 auto', md: 1 },\n alignItems: 'center',\n // Wrapping is the phone's answer, and only the phone's: below `md` the\n // cluster carries the count, the scope control and \"Ações\" at once, and\n // no combination of those fits 320px on one line. From `md` up it stays\n // a single line, where it always fitted.\n flexWrap: { xs: 'wrap', md: 'nowrap' },\n columnGap: 1.5,\n rowGap: 1,\n ml: edgeAlign ? -1.5 : 0,\n }}\n >\n {/* Desktop: a \"Select All\" text button (md+). Mobile: a compact checkbox\n that toggles select-all/clear — the text would eat the tight row. */}\n <Button\n variant=\"text\"\n size=\"small\"\n color=\"inherit\"\n onClick={selectAll}\n data-testid={selectAllTestId}\n sx={{ ...selectionButtonSx, display: { xs: 'none', md: 'inline-flex' } }}\n >\n {selectAllText}\n </Button>\n <Checkbox\n size=\"small\"\n checked={hasSelection}\n onChange={(event) => (event.target.checked ? selectAll() : clearSelection())}\n data-testid={`${selectAllTestId}-checkbox`}\n inputProps={{ 'aria-label': selectAllLabel }}\n sx={{ p: 0.5, display: { xs: 'inline-flex', md: 'none' } }}\n />\n {hasSelection ? (\n <SelectionState\n selectedCount={selectedCount}\n clearSelection={clearSelection}\n clearAllTestId={clearAllTestId}\n clearAllText={clearAllText}\n selectionExtra={selectionExtra}\n />\n ) : null}\n {actionsSlot}\n </Box>\n );\n}\n\n/**\n * What the cluster shows once something IS ticked: Clear All, the count, and\n * the host's own `selectionExtra`.\n *\n * Its own component only because the cluster around it is at the complexity\n * gate's line ceiling — but the split falls where the meaning does. Everything\n * here exists only while a selection does, and the `actions` slot deliberately\n * stays OUTSIDE it: a toolbar may carry actions while browsing too.\n */\nfunction SelectionState({\n selectedCount,\n clearSelection,\n clearAllTestId,\n clearAllText,\n selectionExtra,\n}: Pick<\n ContentToolbarProps,\n 'selectedCount' | 'clearSelection' | 'clearAllTestId' | 'clearAllText' | 'selectionExtra'\n>): React.JSX.Element {\n return (\n <>\n <Button\n variant=\"text\"\n size=\"small\"\n color=\"inherit\"\n onClick={clearSelection}\n data-testid={clearAllTestId}\n sx={selectionButtonSx}\n >\n {clearAllText}\n </Button>\n <Divider orientation=\"vertical\" flexItem sx={{ height: 16, alignSelf: 'center' }} />\n <Typography\n component=\"span\"\n data-testid=\"selected-count-indicator\"\n sx={{ fontSize: '0.875rem', color: 'text.secondary', whiteSpace: 'nowrap', flexShrink: 0 }}\n >\n {selectedCount} {selectedCount === 1 ? 'item' : 'items'} selected\n </Typography>\n {selectionExtra !== undefined && (\n <>\n {/* A DELIBERATE break, not a wrap that happened to land here. What\n follows — \"Seleção: 48 produtos — todas as páginas\", its \"Limpar\n seleção\", and \"Ações\" — is a sentence about the selection plus the\n control that acts on it, and letting the phone break it wherever it\n ran out of room split that sentence mid-phrase. Zero height so it\n costs nothing but the row gap, and `display:none` from `md` up,\n where the line still fits. */}\n <Box\n aria-hidden\n sx={{ flexBasis: '100%', height: 0, display: { xs: 'block', md: 'none' } }}\n />\n {selectionExtra}\n </>\n )}\n </>\n );\n}\n\n/**\n * The BROWSING half of the toolbar: search + filters on the left, the page's\n * own controls on the right. Split out of {@link ContentToolbar} so that\n * function stays inside the complexity gate — it is layout only, and the\n * decision of whether to show it at all is made by the caller.\n */\nfunction BrowsingClusters({\n leadingControls,\n rightControls,\n hasSelection,\n edgeAlign,\n}: {\n leadingControls?: React.ReactNode;\n rightControls: React.ReactNode;\n hasSelection: boolean;\n edgeAlign: boolean;\n}): React.JSX.Element {\n return (\n <>\n {/* minWidth:0 lets this cluster be the one that gives up width as the row\n * tightens, which is what the filter overflow measures against. */}\n {leadingControls !== undefined && (\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n flexGrow: 1,\n minWidth: 0,\n // The collapse ladder has a FLOOR — below roughly 400px even the\n // fully-collapsed row does not fit, and its controls cannot shrink\n // (they are flexShrink:0 so an over-packed row sheds instead of\n // squeezing). Past that point this scrolls rather than letting them\n // paint outside the toolbar, which is what a narrow phone did.\n overflowX: 'auto',\n // No scrollbar gutter stealing height on the common case.\n scrollbarWidth: 'thin',\n }}\n >\n {leadingControls}\n </Box>\n )}\n {/* ml:auto keeps the controls right-aligned even when the cluster wraps to\n * its own row (where justify-content:space-between would otherwise snap a\n * lone item to the left); it's a no-op on a shared row. */}\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n // Same single-line rule as the row itself: this cluster wrapping\n // INTERNALLY buys a second line just as surely as the row wrapping\n // does. It bit at exactly 900px, the `md` breakpoint where the \"N de\n // N\" counter appears and pushes Exibir/Exportar over the edge.\n flexWrap: leadingControls === undefined ? 'wrap' : 'nowrap',\n // Tight (5px) when browsing so the controls fit one line beside the\n // checkbox; roomier (14px) in selection mode where they get their own row.\n gap: hasSelection ? '14px' : '5px',\n ml: 'auto',\n mr: edgeAlign ? -1.5 : 0,\n '& > *': { flexShrink: 0 },\n }}\n >\n {rightControls}\n </Box>\n </>\n );\n}\n\n/**\n * Shared toolbar for content pages (Favorites, Personal Space, Recents, …). The\n * left cluster owns selection chrome — **Select All**, and once items are\n * selected, **Clear All** + an \"N items selected\" count + an optional `actions`\n * slot. The right cluster is a free `rightControls` slot for page-specific\n * controls (ViewSelector, SortByDropdown, MultiSelectDropdown, FilterTrigger).\n *\n * Faithful, generic MUI port of the reference `ContentPageToolbar` — the\n * domain-specific default actions are intentionally left to the consumer via\n * the `actions` slot so this stays agnostic and reusable across projects.\n *\n * @example\n * ```tsx\n * <ContentToolbar\n * hasSelection={selected.size > 0}\n * selectedCount={selected.size}\n * selectAll={selectAll}\n * clearSelection={clear}\n * rightControls={\n * <>\n * <ViewSelector viewMode={view} onViewModeChange={setView} zoom={zoom} onZoomChange={setZoom} />\n * <SortByDropdown fields={FIELDS} activeField={field} onFieldChange={setField} />\n * <MultiSelectDropdown label=\"Content Type\" options={types} selected={typeSet} onToggle={toggle} onClear={clear} />\n * <FilterTrigger open={panelOpen} onOpenChange={setPanelOpen} hasActiveFilters={hasFilters} />\n * </>\n * }\n * />\n * ```\n */\nexport function ContentToolbar({\n hasSelection,\n selectedCount,\n selectAll,\n clearSelection,\n rightControls,\n leadingControls,\n actions,\n selectionExtra,\n selectAllTestId,\n clearAllTestId,\n edgeAlign = false,\n exclusiveSelection = false,\n selectAllLabel,\n selectAllText,\n clearAllText,\n}: ContentToolbarProps): React.JSX.Element {\n // Under `exclusiveSelection` the two states are alternatives, not neighbours:\n // browsing shows the controls and no checkbox, selecting shows the checkbox\n // and no controls. Anything else double-books the row.\n const showSelection = !exclusiveSelection || hasSelection;\n const showControls = !exclusiveSelection || !hasSelection;\n return (\n // Two clusters on one line. They may wrap onto separate rows ONLY for a\n // toolbar without `leadingControls` — one carrying search + filters is\n // driven by a measured collapse ladder (see `useFilterOverflow`), and a\n // wrap there is the ladder having failed: it would silently buy a second\n // row instead of shedding a control into \"Mais\", which is the one outcome\n // the ladder exists to prevent.\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 2,\n flexWrap: leadingControls === undefined ? 'wrap' : 'nowrap',\n rowGap: 1,\n }}\n >\n {showSelection && (\n <SelectionCluster\n selectAllText={selectAllText}\n clearAllText={clearAllText}\n hasSelection={hasSelection}\n selectedCount={selectedCount}\n selectAll={selectAll}\n clearSelection={clearSelection}\n actions={actions}\n selectionExtra={selectionExtra}\n selectAllTestId={selectAllTestId}\n clearAllTestId={clearAllTestId}\n selectAllLabel={selectAllLabel}\n edgeAlign={edgeAlign}\n />\n )}\n\n {showControls && (\n <BrowsingClusters\n leadingControls={leadingControls}\n rightControls={rightControls}\n hasSelection={hasSelection}\n edgeAlign={edgeAlign}\n />\n )}\n </Box>\n );\n}\n"],"mappings":";AAEA,OAAO,SAAS;AAChB,OAAO,YAAY;AACnB,OAAO,cAAc;AACrB,OAAO,aAAa;AACpB,OAAO,gBAAgB;AAiDnB,SAsGI,UAtGJ,KAGA,YAHA;AA5CJ,IAAM,oBAAoB;AAAA,EACxB,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,UAAU;AAAA,EACV,eAAe;AAAA,EACf,OAAO;AACT;AAmBA,SAAS,iBAAiB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AACF,GAA6C;AAC3C,QAAM,cAAc,YAAY,UAC9B,oBAAC,OAAI,IAAI,EAAE,IAAI,KAAK,SAAS,QAAQ,YAAY,GAAG,YAAY,SAAS,GAAI,mBAAQ;AAEvF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,IAAI;AAAA,QACF,SAAS;AAAA,QACT,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAUV,MAAM,EAAE,IAAI,eAAe,aAAa,YAAY,IAAI,EAAE;AAAA,QAC1D,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA,QAKZ,UAAU,EAAE,IAAI,QAAQ,IAAI,SAAS;AAAA,QACrC,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,IAAI,YAAY,OAAO;AAAA,MACzB;AAAA,MAIA;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,OAAM;AAAA,YACN,SAAS;AAAA,YACT,eAAa;AAAA,YACb,IAAI,EAAE,GAAG,mBAAmB,SAAS,EAAE,IAAI,QAAQ,IAAI,cAAc,EAAE;AAAA,YAEtE;AAAA;AAAA,QACH;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAS;AAAA,YACT,UAAU,CAAC,UAAW,MAAM,OAAO,UAAU,UAAU,IAAI,eAAe;AAAA,YAC1E,eAAa,GAAG,eAAe;AAAA,YAC/B,YAAY,EAAE,cAAc,eAAe;AAAA,YAC3C,IAAI,EAAE,GAAG,KAAK,SAAS,EAAE,IAAI,eAAe,IAAI,OAAO,EAAE;AAAA;AAAA,QAC3D;AAAA,QACC,eACC;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA;AAAA,QACF,IACE;AAAA,QACH;AAAA;AAAA;AAAA,EACH;AAEJ;AAWA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAGsB;AACpB,SACE,iCACE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,SAAQ;AAAA,QACR,MAAK;AAAA,QACL,OAAM;AAAA,QACN,SAAS;AAAA,QACT,eAAa;AAAA,QACb,IAAI;AAAA,QAEH;AAAA;AAAA,IACH;AAAA,IACA,oBAAC,WAAQ,aAAY,YAAW,UAAQ,MAAC,IAAI,EAAE,QAAQ,IAAI,WAAW,SAAS,GAAG;AAAA,IAClF;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,eAAY;AAAA,QACZ,IAAI,EAAE,UAAU,YAAY,OAAO,kBAAkB,YAAY,UAAU,YAAY,EAAE;AAAA,QAExF;AAAA;AAAA,UAAc;AAAA,UAAE,kBAAkB,IAAI,SAAS;AAAA,UAAQ;AAAA;AAAA;AAAA,IAC1D;AAAA,IACC,mBAAmB,UAClB,iCAQE;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,eAAW;AAAA,UACX,IAAI,EAAE,WAAW,QAAQ,QAAQ,GAAG,SAAS,EAAE,IAAI,SAAS,IAAI,OAAO,EAAE;AAAA;AAAA,MAC3E;AAAA,MACC;AAAA,OACH;AAAA,KAEJ;AAEJ;AAQA,SAAS,iBAAiB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKsB;AACpB,SACE,iCAGG;AAAA,wBAAoB,UACnB;AAAA,MAAC;AAAA;AAAA,QACC,IAAI;AAAA,UACF,SAAS;AAAA,UACT,YAAY;AAAA,UACZ,UAAU;AAAA,UACV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAMV,WAAW;AAAA;AAAA,UAEX,gBAAgB;AAAA,QAClB;AAAA,QAEC;AAAA;AAAA,IACH;AAAA,IAKF;AAAA,MAAC;AAAA;AAAA,QACC,IAAI;AAAA,UACF,SAAS;AAAA,UACT,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA,UAKZ,UAAU,oBAAoB,SAAY,SAAS;AAAA;AAAA;AAAA,UAGnD,KAAK,eAAe,SAAS;AAAA,UAC7B,IAAI;AAAA,UACJ,IAAI,YAAY,OAAO;AAAA,UACvB,SAAS,EAAE,YAAY,EAAE;AAAA,QAC3B;AAAA,QAEC;AAAA;AAAA,IACH;AAAA,KACF;AAEJ;AA+BO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,qBAAqB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AACF,GAA2C;AAIzC,QAAM,gBAAgB,CAAC,sBAAsB;AAC7C,QAAM,eAAe,CAAC,sBAAsB,CAAC;AAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOE;AAAA,MAAC;AAAA;AAAA,QACC,IAAI;AAAA,UACF,SAAS;AAAA,UACT,YAAY;AAAA,UACZ,gBAAgB;AAAA,UAChB,KAAK;AAAA,UACL,UAAU,oBAAoB,SAAY,SAAS;AAAA,UACnD,QAAQ;AAAA,QACV;AAAA,QAEC;AAAA,2BACC;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA;AAAA,UACF;AAAA,UAGD,gBACC;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA;AAAA,UACF;AAAA;AAAA;AAAA,IAEJ;AAAA;AAEJ;","names":[]}
@@ -23,7 +23,7 @@ import {
23
23
  } from "./chunk-TQ6FPOPD.js";
24
24
  import {
25
25
  ShellToolbar
26
- } from "./chunk-7GKRZJWI.js";
26
+ } from "./chunk-EMMPNB6D.js";
27
27
  import {
28
28
  resolveSelectionExtra
29
29
  } from "./chunk-KX75HM5U.js";
@@ -237,4 +237,4 @@ function GridShell(props) {
237
237
  export {
238
238
  GridShell
239
239
  };
240
- //# sourceMappingURL=chunk-NXNNICH7.js.map
240
+ //# sourceMappingURL=chunk-LWRMKF7D.js.map
@@ -1,6 +1,6 @@
1
1
  // src/components/data-display/CardKit/row-actions-to-menu.ts
2
2
  function rowActionsToMenuItems(actions, row) {
3
- return actions.filter((action) => action.isVisible?.(row) ?? true).map((action) => ({
3
+ return actions.filter((action) => action.row !== false).filter((action) => action.isVisible?.(row) ?? true).map((action) => ({
4
4
  id: action.id,
5
5
  label: action.rowLabel?.(row) ?? action.label,
6
6
  color: action.color,
@@ -11,4 +11,4 @@ function rowActionsToMenuItems(actions, row) {
11
11
  export {
12
12
  rowActionsToMenuItems
13
13
  };
14
- //# sourceMappingURL=chunk-5MXVT7DO.js.map
14
+ //# sourceMappingURL=chunk-ZBXG6RVJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/data-display/CardKit/row-actions-to-menu.ts"],"sourcesContent":["import type { DropdownMenuItem } from '../../navigation/DropdownMenu';\nimport type { RowAction } from '../DataViews';\n\n/**\n * Adapt a list of {@link RowAction}s into single-row kebab items.\n *\n * Drops the actions that declare `row: false`, applies each survivor's\n * `isVisible` guard, resolves its per-row `rowLabel` override, carries its\n * colour, and fires `onSelect([row])` on click.\n *\n * The point is that ONE definition drives both surfaces. An entity that already\n * declares its per-row actions as `RowAction[]` — because the table's multi-\n * select menu needs them — gets the card's kebab from the same array through\n * `renderRowMenu` / `renderCard`, with no second list to keep in step. Two\n * lists is how a \"Duplicar\" that appears in the table and not on the card\n * happens, and nothing reports it.\n *\n * ## Why `row: false` is filtered HERE\n *\n * `row` and `bulk` are the flags that make one list serve two surfaces, so an\n * adapter that ignores one of them defeats the arrangement it exists to\n * support. This one did, and the result was a per-row \"⋮\" on Produtos offering\n * \"Inativar todos\", \"Destacar todos\" and \"Remover destaque de todos\" beside\n * that row's own \"Inativar\" and \"Remover destaque\" — bulk verbs on a menu whose\n * every other entry means \"this one\", where \"todos\" reads as the whole\n * catalogue and the click actually writes a single row.\n *\n * The bulk half was already honoured (`renderBulkActions` filters `bulk`), so\n * only the kebab leaked. Filtering here fixes it for every surface that builds\n * a kebab from `RowAction[]` — the table row, the grid card and the list card\n * all arrive through this function.\n */\nexport function rowActionsToMenuItems<T extends Record<string, unknown>>(\n actions: RowAction<T>[],\n row: T,\n): DropdownMenuItem[] {\n return actions\n .filter((action) => action.row !== false)\n .filter((action) => action.isVisible?.(row) ?? true)\n .map((action) => ({\n id: action.id,\n label: action.rowLabel?.(row) ?? action.label,\n color: action.color,\n onClick: () => void action.onSelect([row]),\n }));\n}\n"],"mappings":";AAgCO,SAAS,sBACd,SACA,KACoB;AACpB,SAAO,QACJ,OAAO,CAAC,WAAW,OAAO,QAAQ,KAAK,EACvC,OAAO,CAAC,WAAW,OAAO,YAAY,GAAG,KAAK,IAAI,EAClD,IAAI,CAAC,YAAY;AAAA,IAChB,IAAI,OAAO;AAAA,IACX,OAAO,OAAO,WAAW,GAAG,KAAK,OAAO;AAAA,IACxC,OAAO,OAAO;AAAA,IACd,SAAS,MAAM,KAAK,OAAO,SAAS,CAAC,GAAG,CAAC;AAAA,EAC3C,EAAE;AACN;","names":[]}
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-4X4KM4ZB.js";
4
4
  import {
5
5
  DataViewsGrid
6
- } from "./chunk-QX2PLXQA.js";
6
+ } from "./chunk-53PDVLRK.js";
7
7
  import {
8
8
  viewStateKey
9
9
  } from "./chunk-ZOLAYP2D.js";
@@ -178,4 +178,4 @@ function renderViewDialogs(ctl, fields, columns, views, testIdPrefix, onSaved) {
178
178
  export {
179
179
  DataViewsTableBase
180
180
  };
181
- //# sourceMappingURL=chunk-JPV45AD6.js.map
181
+ //# sourceMappingURL=chunk-ZXOT3U6U.js.map
@@ -3,7 +3,7 @@ import {
3
3
  } from "../chunk-KM5O4ICK.js";
4
4
  import {
5
5
  rowActionsToMenuItems
6
- } from "../chunk-5MXVT7DO.js";
6
+ } from "../chunk-ZBXG6RVJ.js";
7
7
  import {
8
8
  BodyHeading,
9
9
  DetailColumns,
@@ -3,11 +3,11 @@ import {
3
3
  } from "../chunk-JWW2Z3RH.js";
4
4
  import {
5
5
  DataViewsTableBase
6
- } from "../chunk-JPV45AD6.js";
6
+ } from "../chunk-ZXOT3U6U.js";
7
7
  import "../chunk-4X4KM4ZB.js";
8
8
  import {
9
9
  DataViewsGrid
10
- } from "../chunk-QX2PLXQA.js";
10
+ } from "../chunk-53PDVLRK.js";
11
11
  import {
12
12
  BaseListCard
13
13
  } from "../chunk-WR5JFDQ5.js";
@@ -22,7 +22,7 @@ import {
22
22
  DropIndicator,
23
23
  useDragItem
24
24
  } from "../chunk-JCJGJX7V.js";
25
- import "../chunk-NXNNICH7.js";
25
+ import "../chunk-LWRMKF7D.js";
26
26
  import "../chunk-BPLFM2GL.js";
27
27
  import {
28
28
  DataViewsBoard
@@ -43,7 +43,7 @@ import "../chunk-CBOB5AV6.js";
43
43
  import "../chunk-HP2ODXNA.js";
44
44
  import "../chunk-TQ6FPOPD.js";
45
45
  import "../chunk-IAGOUTI6.js";
46
- import "../chunk-7GKRZJWI.js";
46
+ import "../chunk-EMMPNB6D.js";
47
47
  import "../chunk-KX75HM5U.js";
48
48
  import "../chunk-XKV5ZIBG.js";
49
49
  import "../chunk-A7Q5AQVD.js";
@@ -56,7 +56,7 @@ import {
56
56
  import {
57
57
  DEFAULT_CELL_WIDTH
58
58
  } from "../chunk-6VP2L3DJ.js";
59
- import "../chunk-JD4IVP22.js";
59
+ import "../chunk-4ZV7N5CU.js";
60
60
  import "../chunk-SQNW22ZZ.js";
61
61
  import "../chunk-7NSX7A5H.js";
62
62
  import "../chunk-DW5FRWRQ.js";
@@ -108,7 +108,7 @@ import "../chunk-7AIL2F5E.js";
108
108
  import "../chunk-WVML3ENZ.js";
109
109
  import "../chunk-IDHZHOZW.js";
110
110
  import "../chunk-MOLQGQEQ.js";
111
- import "../chunk-TSPHRZ4U.js";
111
+ import "../chunk-L2E7TY7P.js";
112
112
  import "../chunk-JMVIIKII.js";
113
113
  import "../chunk-WXD7MGBT.js";
114
114
  import "../chunk-WQFIV5WD.js";
@@ -1,7 +1,7 @@
1
1
  import "../chunk-MOLQGQEQ.js";
2
2
  import {
3
3
  ContentToolbar
4
- } from "../chunk-TSPHRZ4U.js";
4
+ } from "../chunk-L2E7TY7P.js";
5
5
  import {
6
6
  ColumnsMenu
7
7
  } from "../chunk-JMVIIKII.js";
@@ -3,8 +3,9 @@ import type { RowAction } from '../DataViews';
3
3
  /**
4
4
  * Adapt a list of {@link RowAction}s into single-row kebab items.
5
5
  *
6
- * Applies each action's `isVisible` guard, resolves its per-row `rowLabel`
7
- * override, carries its colour, and fires `onSelect([row])` on click.
6
+ * Drops the actions that declare `row: false`, applies each survivor's
7
+ * `isVisible` guard, resolves its per-row `rowLabel` override, carries its
8
+ * colour, and fires `onSelect([row])` on click.
8
9
  *
9
10
  * The point is that ONE definition drives both surfaces. An entity that already
10
11
  * declares its per-row actions as `RowAction[]` — because the table's multi-
@@ -12,6 +13,21 @@ import type { RowAction } from '../DataViews';
12
13
  * `renderRowMenu` / `renderCard`, with no second list to keep in step. Two
13
14
  * lists is how a "Duplicar" that appears in the table and not on the card
14
15
  * happens, and nothing reports it.
16
+ *
17
+ * ## Why `row: false` is filtered HERE
18
+ *
19
+ * `row` and `bulk` are the flags that make one list serve two surfaces, so an
20
+ * adapter that ignores one of them defeats the arrangement it exists to
21
+ * support. This one did, and the result was a per-row "⋮" on Produtos offering
22
+ * "Inativar todos", "Destacar todos" and "Remover destaque de todos" beside
23
+ * that row's own "Inativar" and "Remover destaque" — bulk verbs on a menu whose
24
+ * every other entry means "this one", where "todos" reads as the whole
25
+ * catalogue and the click actually writes a single row.
26
+ *
27
+ * The bulk half was already honoured (`renderBulkActions` filters `bulk`), so
28
+ * only the kebab leaked. Filtering here fixes it for every surface that builds
29
+ * a kebab from `RowAction[]` — the table row, the grid card and the list card
30
+ * all arrive through this function.
15
31
  */
16
32
  export declare function rowActionsToMenuItems<T extends Record<string, unknown>>(actions: RowAction<T>[], row: T): DropdownMenuItem[];
17
33
  //# sourceMappingURL=row-actions-to-menu.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"row-actions-to-menu.d.ts","sourceRoot":"","sources":["../../../../../src/components/data-display/CardKit/row-actions-to-menu.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,EACvB,GAAG,EAAE,CAAC,GACL,gBAAgB,EAAE,CASpB"}
1
+ {"version":3,"file":"row-actions-to-menu.d.ts","sourceRoot":"","sources":["../../../../../src/components/data-display/CardKit/row-actions-to-menu.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,EACvB,GAAG,EAAE,CAAC,GACL,gBAAgB,EAAE,CAUpB"}
@@ -1 +1 @@
1
- {"version":3,"file":"ContentToolbar.d.ts","sourceRoot":"","sources":["../../../../../src/components/layout/ContentToolbar/ContentToolbar.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAkLlE;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,cAAc,CAAC,EAC7B,YAAY,EACZ,aAAa,EACb,SAAS,EACT,cAAc,EACd,aAAa,EACb,eAAe,EACf,OAAO,EACP,cAAc,EACd,eAAe,EACf,cAAc,EACd,SAAiB,EACjB,kBAA0B,EAC1B,cAAc,EACd,aAAa,EACb,YAAY,GACb,EAAE,mBAAmB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAkDzC"}
1
+ {"version":3,"file":"ContentToolbar.d.ts","sourceRoot":"","sources":["../../../../../src/components/layout/ContentToolbar/ContentToolbar.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AA0OlE;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,cAAc,CAAC,EAC7B,YAAY,EACZ,aAAa,EACb,SAAS,EACT,cAAc,EACd,aAAa,EACb,eAAe,EACf,OAAO,EACP,cAAc,EACd,eAAe,EACf,cAAc,EACd,SAAiB,EACjB,kBAA0B,EAC1B,cAAc,EACd,aAAa,EACb,YAAY,GACb,EAAE,mBAAmB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAkDzC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@12-apps/ui",
3
- "version": "6.24.4",
3
+ "version": "6.24.5",
4
4
  "license": "MIT",
5
5
  "packageManager": "pnpm@10.34.5",
6
6
  "type": "module",
@@ -4,8 +4,9 @@ import type { RowAction } from '../DataViews';
4
4
  /**
5
5
  * Adapt a list of {@link RowAction}s into single-row kebab items.
6
6
  *
7
- * Applies each action's `isVisible` guard, resolves its per-row `rowLabel`
8
- * override, carries its colour, and fires `onSelect([row])` on click.
7
+ * Drops the actions that declare `row: false`, applies each survivor's
8
+ * `isVisible` guard, resolves its per-row `rowLabel` override, carries its
9
+ * colour, and fires `onSelect([row])` on click.
9
10
  *
10
11
  * The point is that ONE definition drives both surfaces. An entity that already
11
12
  * declares its per-row actions as `RowAction[]` — because the table's multi-
@@ -13,12 +14,28 @@ import type { RowAction } from '../DataViews';
13
14
  * `renderRowMenu` / `renderCard`, with no second list to keep in step. Two
14
15
  * lists is how a "Duplicar" that appears in the table and not on the card
15
16
  * happens, and nothing reports it.
17
+ *
18
+ * ## Why `row: false` is filtered HERE
19
+ *
20
+ * `row` and `bulk` are the flags that make one list serve two surfaces, so an
21
+ * adapter that ignores one of them defeats the arrangement it exists to
22
+ * support. This one did, and the result was a per-row "⋮" on Produtos offering
23
+ * "Inativar todos", "Destacar todos" and "Remover destaque de todos" beside
24
+ * that row's own "Inativar" and "Remover destaque" — bulk verbs on a menu whose
25
+ * every other entry means "this one", where "todos" reads as the whole
26
+ * catalogue and the click actually writes a single row.
27
+ *
28
+ * The bulk half was already honoured (`renderBulkActions` filters `bulk`), so
29
+ * only the kebab leaked. Filtering here fixes it for every surface that builds
30
+ * a kebab from `RowAction[]` — the table row, the grid card and the list card
31
+ * all arrive through this function.
16
32
  */
17
33
  export function rowActionsToMenuItems<T extends Record<string, unknown>>(
18
34
  actions: RowAction<T>[],
19
35
  row: T,
20
36
  ): DropdownMenuItem[] {
21
37
  return actions
38
+ .filter((action) => action.row !== false)
22
39
  .filter((action) => action.isVisible?.(row) ?? true)
23
40
  .map((action) => ({
24
41
  id: action.id,
@@ -46,6 +46,49 @@ Everything below exists to keep that true. When a change breaks it, the fix is
46
46
  another rung on the ladder — never a scrollbar, and never letting controls paint
47
47
  outside the toolbar.
48
48
 
49
+ **"One line" is a rule about BROWSING.** Everything in this document describes
50
+ the row an operator reads a list from, and the ladder measures that row. The
51
+ selection row is a different row with different contents and no ladder at all —
52
+ see below.
53
+
54
+ ---
55
+
56
+ ## The selection row
57
+
58
+ Tick a checkbox and `exclusiveSelection` hands the whole toolbar to the
59
+ selection cluster: the search, the filters, Exibir and Exportar all stand down,
60
+ and what is left is "Limpar filtros", the count, whatever the host puts in
61
+ `selectionExtra`, and the actions menu.
62
+
63
+ That cluster is not on the ladder, and it must not be. The ladder sheds controls
64
+ because each one it sheds has somewhere else to be — a filter into "Mais", a
65
+ label into an icon, "Limpar" into a panel footer. Nothing here does. Dropping
66
+ the count loses the only statement of what is about to be written to; dropping
67
+ "Ações" loses the reason the operator ticked anything.
68
+
69
+ **So below `md` it WRAPS instead**, which is the one thing the browsing row may
70
+ never do:
71
+
72
+ | | small mobile | large mobile | tablet | desktop |
73
+ | --- | --- | --- | --- | --- |
74
+ | checkbox + "Limpar filtros" + count | line 1 | line 1 | line 1 | line 1 |
75
+ | `selectionExtra` + "Ações" | line 2 | line 2 | line 2 | line 1 |
76
+
77
+ The break before `selectionExtra` is deliberate rather than wherever the row ran
78
+ out of room. What follows it is one thought — what the selection IS ("Seleção:
79
+ 48 produtos — todas as páginas" and its "Limpar seleção") plus the control that
80
+ acts on it — and a natural wrap split that thought mid-phrase.
81
+
82
+ Before this, the cluster was pinned at content width with every child
83
+ `flex-shrink: 0`. On Produtos with the scope armed that is ~766px of controls,
84
+ so at 320 the row painted 446px past the toolbar's own edge and "Ações" sat
85
+ off-screen behind a sideways scroll of the document. The button the whole
86
+ selection exists to reach was the one you could not see.
87
+
88
+ `ContentToolbar.stories.tsx` → **NarrowSelectionOverflow** is that exact row.
89
+ Open it at 320 and 390; jsdom cannot see this failure, so no unit test can
90
+ guard it.
91
+
49
92
  ---
50
93
 
51
94
  ## The ladder
@@ -60,11 +60,24 @@ function SelectionCluster({
60
60
  sx={{
61
61
  display: 'flex',
62
62
  minWidth: 0,
63
- // Mobile: don't grow, so the controls sit on the SAME line as the checkbox
64
- // (no orphaned selection row). Desktop: grow to push controls right.
65
- flex: { xs: '0 0 auto', md: 1 },
63
+ // Browsing (mobile): don't grow, so the controls sit on the SAME line as
64
+ // the checkbox (no orphaned selection row). Desktop: grow to push
65
+ // controls right.
66
+ //
67
+ // SELECTING (mobile) it must be able to shrink instead. Its children are
68
+ // all `flex-shrink: 0`, so a cluster pinned at content width cannot wrap
69
+ // and the row painted past the toolbar's own edge — on Produtos at 390px
70
+ // that took "Ações" off-screen behind a sideways scroll, which is the
71
+ // one control the selection exists to reach.
72
+ flex: { xs: hasSelection ? '1 1 auto' : '0 0 auto', md: 1 },
66
73
  alignItems: 'center',
67
- gap: 1.5,
74
+ // Wrapping is the phone's answer, and only the phone's: below `md` the
75
+ // cluster carries the count, the scope control and "Ações" at once, and
76
+ // no combination of those fits 320px on one line. From `md` up it stays
77
+ // a single line, where it always fitted.
78
+ flexWrap: { xs: 'wrap', md: 'nowrap' },
79
+ columnGap: 1.5,
80
+ rowGap: 1,
68
81
  ml: edgeAlign ? -1.5 : 0,
69
82
  }}
70
83
  >
@@ -89,32 +102,75 @@ function SelectionCluster({
89
102
  sx={{ p: 0.5, display: { xs: 'inline-flex', md: 'none' } }}
90
103
  />
91
104
  {hasSelection ? (
105
+ <SelectionState
106
+ selectedCount={selectedCount}
107
+ clearSelection={clearSelection}
108
+ clearAllTestId={clearAllTestId}
109
+ clearAllText={clearAllText}
110
+ selectionExtra={selectionExtra}
111
+ />
112
+ ) : null}
113
+ {actionsSlot}
114
+ </Box>
115
+ );
116
+ }
117
+
118
+ /**
119
+ * What the cluster shows once something IS ticked: Clear All, the count, and
120
+ * the host's own `selectionExtra`.
121
+ *
122
+ * Its own component only because the cluster around it is at the complexity
123
+ * gate's line ceiling — but the split falls where the meaning does. Everything
124
+ * here exists only while a selection does, and the `actions` slot deliberately
125
+ * stays OUTSIDE it: a toolbar may carry actions while browsing too.
126
+ */
127
+ function SelectionState({
128
+ selectedCount,
129
+ clearSelection,
130
+ clearAllTestId,
131
+ clearAllText,
132
+ selectionExtra,
133
+ }: Pick<
134
+ ContentToolbarProps,
135
+ 'selectedCount' | 'clearSelection' | 'clearAllTestId' | 'clearAllText' | 'selectionExtra'
136
+ >): React.JSX.Element {
137
+ return (
138
+ <>
139
+ <Button
140
+ variant="text"
141
+ size="small"
142
+ color="inherit"
143
+ onClick={clearSelection}
144
+ data-testid={clearAllTestId}
145
+ sx={selectionButtonSx}
146
+ >
147
+ {clearAllText}
148
+ </Button>
149
+ <Divider orientation="vertical" flexItem sx={{ height: 16, alignSelf: 'center' }} />
150
+ <Typography
151
+ component="span"
152
+ data-testid="selected-count-indicator"
153
+ sx={{ fontSize: '0.875rem', color: 'text.secondary', whiteSpace: 'nowrap', flexShrink: 0 }}
154
+ >
155
+ {selectedCount} {selectedCount === 1 ? 'item' : 'items'} selected
156
+ </Typography>
157
+ {selectionExtra !== undefined && (
92
158
  <>
93
- <Button
94
- variant="text"
95
- size="small"
96
- color="inherit"
97
- onClick={clearSelection}
98
- data-testid={clearAllTestId}
99
- sx={selectionButtonSx}
100
- >
101
- {clearAllText}
102
- </Button>
103
- <Divider orientation="vertical" flexItem sx={{ height: 16, alignSelf: 'center' }} />
104
- <Typography
105
- component="span"
106
- data-testid="selected-count-indicator"
107
- sx={{ fontSize: '0.875rem', color: 'text.secondary', whiteSpace: 'nowrap', flexShrink: 0 }}
108
- >
109
- {selectedCount} {selectedCount === 1 ? 'item' : 'items'} selected
110
- </Typography>
159
+ {/* A DELIBERATE break, not a wrap that happened to land here. What
160
+ follows — "Seleção: 48 produtos — todas as páginas", its "Limpar
161
+ seleção", and "Ações" — is a sentence about the selection plus the
162
+ control that acts on it, and letting the phone break it wherever it
163
+ ran out of room split that sentence mid-phrase. Zero height so it
164
+ costs nothing but the row gap, and `display:none` from `md` up,
165
+ where the line still fits. */}
166
+ <Box
167
+ aria-hidden
168
+ sx={{ flexBasis: '100%', height: 0, display: { xs: 'block', md: 'none' } }}
169
+ />
111
170
  {selectionExtra}
112
- {actionsSlot}
113
171
  </>
114
- ) : (
115
- actionsSlot
116
172
  )}
117
- </Box>
173
+ </>
118
174
  );
119
175
  }
120
176
 
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/CardKit/row-actions-to-menu.ts"],"sourcesContent":["import type { DropdownMenuItem } from '../../navigation/DropdownMenu';\nimport type { RowAction } from '../DataViews';\n\n/**\n * Adapt a list of {@link RowAction}s into single-row kebab items.\n *\n * Applies each action's `isVisible` guard, resolves its per-row `rowLabel`\n * override, carries its colour, and fires `onSelect([row])` on click.\n *\n * The point is that ONE definition drives both surfaces. An entity that already\n * declares its per-row actions as `RowAction[]` — because the table's multi-\n * select menu needs them — gets the card's kebab from the same array through\n * `renderRowMenu` / `renderCard`, with no second list to keep in step. Two\n * lists is how a \"Duplicar\" that appears in the table and not on the card\n * happens, and nothing reports it.\n */\nexport function rowActionsToMenuItems<T extends Record<string, unknown>>(\n actions: RowAction<T>[],\n row: T,\n): DropdownMenuItem[] {\n return actions\n .filter((action) => action.isVisible?.(row) ?? true)\n .map((action) => ({\n id: action.id,\n label: action.rowLabel?.(row) ?? action.label,\n color: action.color,\n onClick: () => void action.onSelect([row]),\n }));\n}\n"],"mappings":";AAgBO,SAAS,sBACd,SACA,KACoB;AACpB,SAAO,QACJ,OAAO,CAAC,WAAW,OAAO,YAAY,GAAG,KAAK,IAAI,EAClD,IAAI,CAAC,YAAY;AAAA,IAChB,IAAI,OAAO;AAAA,IACX,OAAO,OAAO,WAAW,GAAG,KAAK,OAAO;AAAA,IACxC,OAAO,OAAO;AAAA,IACd,SAAS,MAAM,KAAK,OAAO,SAAS,CAAC,GAAG,CAAC;AAAA,EAC3C,EAAE;AACN;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/layout/ContentToolbar/ContentToolbar.tsx"],"sourcesContent":["'use client';\n\nimport Box from '@mui/material/Box/index.js';\nimport Button from '@mui/material/Button/index.js';\nimport Checkbox from '@mui/material/Checkbox/index.js';\nimport Divider from '@mui/material/Divider/index.js';\nimport Typography from '@mui/material/Typography/index.js';\nimport React from 'react';\n\nimport type { ContentToolbarProps } from './ContentToolbar.types';\n\nconst selectionButtonSx = {\n minWidth: 0,\n height: 'auto',\n borderRadius: 0.5,\n fontWeight: 600,\n py: 0.5,\n px: 1.5,\n fontSize: '0.75rem',\n textTransform: 'none',\n color: 'text.primary',\n} as const;\n\ntype SelectionClusterProps = Pick<\n ContentToolbarProps,\n | 'hasSelection'\n | 'selectedCount'\n | 'selectAll'\n | 'clearSelection'\n | 'actions'\n | 'selectionExtra'\n | 'selectAllTestId'\n | 'clearAllTestId'\n | 'edgeAlign'\n | 'selectAllLabel'\n | 'selectAllText'\n | 'clearAllText'\n>;\n\n/** The left cluster: Select All + (when selecting) Clear All / count / actions. */\nfunction SelectionCluster({\n hasSelection,\n selectedCount,\n selectAll,\n clearSelection,\n actions,\n selectionExtra,\n selectAllTestId,\n clearAllTestId,\n edgeAlign = false,\n selectAllLabel,\n selectAllText,\n clearAllText,\n}: SelectionClusterProps): React.JSX.Element {\n const actionsSlot = actions !== undefined && (\n <Box sx={{ ml: 0.5, display: 'flex', flexShrink: 0, alignItems: 'center' }}>{actions}</Box>\n );\n return (\n <Box\n sx={{\n display: 'flex',\n minWidth: 0,\n // Mobile: don't grow, so the controls sit on the SAME line as the checkbox\n // (no orphaned selection row). Desktop: grow to push controls right.\n flex: { xs: '0 0 auto', md: 1 },\n alignItems: 'center',\n gap: 1.5,\n ml: edgeAlign ? -1.5 : 0,\n }}\n >\n {/* Desktop: a \"Select All\" text button (md+). Mobile: a compact checkbox\n that toggles select-all/clear — the text would eat the tight row. */}\n <Button\n variant=\"text\"\n size=\"small\"\n color=\"inherit\"\n onClick={selectAll}\n data-testid={selectAllTestId}\n sx={{ ...selectionButtonSx, display: { xs: 'none', md: 'inline-flex' } }}\n >\n {selectAllText}\n </Button>\n <Checkbox\n size=\"small\"\n checked={hasSelection}\n onChange={(event) => (event.target.checked ? selectAll() : clearSelection())}\n data-testid={`${selectAllTestId}-checkbox`}\n inputProps={{ 'aria-label': selectAllLabel }}\n sx={{ p: 0.5, display: { xs: 'inline-flex', md: 'none' } }}\n />\n {hasSelection ? (\n <>\n <Button\n variant=\"text\"\n size=\"small\"\n color=\"inherit\"\n onClick={clearSelection}\n data-testid={clearAllTestId}\n sx={selectionButtonSx}\n >\n {clearAllText}\n </Button>\n <Divider orientation=\"vertical\" flexItem sx={{ height: 16, alignSelf: 'center' }} />\n <Typography\n component=\"span\"\n data-testid=\"selected-count-indicator\"\n sx={{ fontSize: '0.875rem', color: 'text.secondary', whiteSpace: 'nowrap', flexShrink: 0 }}\n >\n {selectedCount} {selectedCount === 1 ? 'item' : 'items'} selected\n </Typography>\n {selectionExtra}\n {actionsSlot}\n </>\n ) : (\n actionsSlot\n )}\n </Box>\n );\n}\n\n/**\n * The BROWSING half of the toolbar: search + filters on the left, the page's\n * own controls on the right. Split out of {@link ContentToolbar} so that\n * function stays inside the complexity gate — it is layout only, and the\n * decision of whether to show it at all is made by the caller.\n */\nfunction BrowsingClusters({\n leadingControls,\n rightControls,\n hasSelection,\n edgeAlign,\n}: {\n leadingControls?: React.ReactNode;\n rightControls: React.ReactNode;\n hasSelection: boolean;\n edgeAlign: boolean;\n}): React.JSX.Element {\n return (\n <>\n {/* minWidth:0 lets this cluster be the one that gives up width as the row\n * tightens, which is what the filter overflow measures against. */}\n {leadingControls !== undefined && (\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n flexGrow: 1,\n minWidth: 0,\n // The collapse ladder has a FLOOR — below roughly 400px even the\n // fully-collapsed row does not fit, and its controls cannot shrink\n // (they are flexShrink:0 so an over-packed row sheds instead of\n // squeezing). Past that point this scrolls rather than letting them\n // paint outside the toolbar, which is what a narrow phone did.\n overflowX: 'auto',\n // No scrollbar gutter stealing height on the common case.\n scrollbarWidth: 'thin',\n }}\n >\n {leadingControls}\n </Box>\n )}\n {/* ml:auto keeps the controls right-aligned even when the cluster wraps to\n * its own row (where justify-content:space-between would otherwise snap a\n * lone item to the left); it's a no-op on a shared row. */}\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n // Same single-line rule as the row itself: this cluster wrapping\n // INTERNALLY buys a second line just as surely as the row wrapping\n // does. It bit at exactly 900px, the `md` breakpoint where the \"N de\n // N\" counter appears and pushes Exibir/Exportar over the edge.\n flexWrap: leadingControls === undefined ? 'wrap' : 'nowrap',\n // Tight (5px) when browsing so the controls fit one line beside the\n // checkbox; roomier (14px) in selection mode where they get their own row.\n gap: hasSelection ? '14px' : '5px',\n ml: 'auto',\n mr: edgeAlign ? -1.5 : 0,\n '& > *': { flexShrink: 0 },\n }}\n >\n {rightControls}\n </Box>\n </>\n );\n}\n\n/**\n * Shared toolbar for content pages (Favorites, Personal Space, Recents, …). The\n * left cluster owns selection chrome — **Select All**, and once items are\n * selected, **Clear All** + an \"N items selected\" count + an optional `actions`\n * slot. The right cluster is a free `rightControls` slot for page-specific\n * controls (ViewSelector, SortByDropdown, MultiSelectDropdown, FilterTrigger).\n *\n * Faithful, generic MUI port of the reference `ContentPageToolbar` — the\n * domain-specific default actions are intentionally left to the consumer via\n * the `actions` slot so this stays agnostic and reusable across projects.\n *\n * @example\n * ```tsx\n * <ContentToolbar\n * hasSelection={selected.size > 0}\n * selectedCount={selected.size}\n * selectAll={selectAll}\n * clearSelection={clear}\n * rightControls={\n * <>\n * <ViewSelector viewMode={view} onViewModeChange={setView} zoom={zoom} onZoomChange={setZoom} />\n * <SortByDropdown fields={FIELDS} activeField={field} onFieldChange={setField} />\n * <MultiSelectDropdown label=\"Content Type\" options={types} selected={typeSet} onToggle={toggle} onClear={clear} />\n * <FilterTrigger open={panelOpen} onOpenChange={setPanelOpen} hasActiveFilters={hasFilters} />\n * </>\n * }\n * />\n * ```\n */\nexport function ContentToolbar({\n hasSelection,\n selectedCount,\n selectAll,\n clearSelection,\n rightControls,\n leadingControls,\n actions,\n selectionExtra,\n selectAllTestId,\n clearAllTestId,\n edgeAlign = false,\n exclusiveSelection = false,\n selectAllLabel,\n selectAllText,\n clearAllText,\n}: ContentToolbarProps): React.JSX.Element {\n // Under `exclusiveSelection` the two states are alternatives, not neighbours:\n // browsing shows the controls and no checkbox, selecting shows the checkbox\n // and no controls. Anything else double-books the row.\n const showSelection = !exclusiveSelection || hasSelection;\n const showControls = !exclusiveSelection || !hasSelection;\n return (\n // Two clusters on one line. They may wrap onto separate rows ONLY for a\n // toolbar without `leadingControls` — one carrying search + filters is\n // driven by a measured collapse ladder (see `useFilterOverflow`), and a\n // wrap there is the ladder having failed: it would silently buy a second\n // row instead of shedding a control into \"Mais\", which is the one outcome\n // the ladder exists to prevent.\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 2,\n flexWrap: leadingControls === undefined ? 'wrap' : 'nowrap',\n rowGap: 1,\n }}\n >\n {showSelection && (\n <SelectionCluster\n selectAllText={selectAllText}\n clearAllText={clearAllText}\n hasSelection={hasSelection}\n selectedCount={selectedCount}\n selectAll={selectAll}\n clearSelection={clearSelection}\n actions={actions}\n selectionExtra={selectionExtra}\n selectAllTestId={selectAllTestId}\n clearAllTestId={clearAllTestId}\n selectAllLabel={selectAllLabel}\n edgeAlign={edgeAlign}\n />\n )}\n\n {showControls && (\n <BrowsingClusters\n leadingControls={leadingControls}\n rightControls={rightControls}\n hasSelection={hasSelection}\n edgeAlign={edgeAlign}\n />\n )}\n </Box>\n );\n}\n"],"mappings":"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","names":[]}