@12-apps/ui 6.57.0 → 6.59.0

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 (210) hide show
  1. package/dist/_internal/components/data-display/Avatar/Avatar.js +2 -2
  2. package/dist/_internal/components/data-display/Badge/Badge.js +2 -2
  3. package/dist/_internal/components/data-display/Carousel/Carousel.js +2 -2
  4. package/dist/_internal/components/data-display/Chart/Chart.js +4 -4
  5. package/dist/_internal/components/data-display/Chart/SpecChart.js +7 -7
  6. package/dist/_internal/components/data-display/Chart/chart-context.js +2 -2
  7. package/dist/_internal/components/data-display/Chart/chart-format.js +5 -1
  8. package/dist/_internal/components/data-display/Chart/chart-renderers.js +3 -3
  9. package/dist/_internal/components/data-display/Chart/chart-spec.js +2 -2
  10. package/dist/_internal/components/data-display/DataGrid/DataGrid.js +2 -2
  11. package/dist/_internal/components/data-display/DataViews/DataViewsGrid.js +18 -18
  12. package/dist/_internal/components/data-display/DataViews/DataViewsTableBase.js +20 -19
  13. package/dist/_internal/components/data-display/DataViews/base-list-card-geometry.js +5 -3
  14. package/dist/_internal/components/data-display/DataViews/base-list-card-layout.js +45 -0
  15. package/dist/_internal/components/data-display/DataViews/base-list-card-layout.js.map +1 -0
  16. package/dist/_internal/components/data-display/DataViews/base-list-card-slots.js +2 -2
  17. package/dist/_internal/components/data-display/DataViews/base-list-card.js +5 -4
  18. package/dist/_internal/components/data-display/DataViews/data-views-category-pill.js +1 -1
  19. package/dist/_internal/components/data-display/DataViews/data-views-filter-panel.js +4 -4
  20. package/dist/_internal/components/data-display/DataViews/data-views-grid-bodies.js +4 -4
  21. package/dist/_internal/components/data-display/DataViews/data-views-grid-parts.js +17 -17
  22. package/dist/_internal/components/data-display/DataViews/data-views-inline-bar.js +6 -6
  23. package/dist/_internal/components/data-display/DataViews/data-views-more-fields.js +4 -4
  24. package/dist/_internal/components/data-display/DataViews/data-views-more-filters.js +5 -5
  25. package/dist/_internal/components/data-display/DataViews/data-views-range-pill.js +2 -2
  26. package/dist/_internal/components/data-display/DataViews/data-views-selection-extra.js +3 -1
  27. package/dist/_internal/components/data-display/DataViews/data-views-shell-toolbar.js +3 -3
  28. package/dist/_internal/components/data-display/DataViews/data-views-table-parts.js +1 -1
  29. package/dist/_internal/components/data-display/DataViews/data-views-toolbar.js +2 -2
  30. package/dist/_internal/components/data-display/DataViews/data-views-url-echo.js +13 -0
  31. package/dist/_internal/components/data-display/DataViews/data-views-url-echo.js.map +1 -0
  32. package/dist/_internal/components/data-display/DataViews/list-card-rails.js +1 -1
  33. package/dist/_internal/components/data-display/FleetMap/FleetMap.fixtures.js +1 -1
  34. package/dist/_internal/components/data-display/index.js +16 -16
  35. package/dist/_internal/components/index.js +24 -24
  36. package/dist/_internal/components/layout/ContentToolbar/ContentToolbar.js +1 -1
  37. package/dist/_internal/components/layout/index.js +1 -1
  38. package/dist/_internal/components/navigation/SectionNav/SectionNav.bar.js +6 -6
  39. package/dist/_internal/components/navigation/SectionNav/SectionNav.js +9 -9
  40. package/dist/_internal/components/navigation/SectionNav/SectionNav.parts.js +3 -3
  41. package/dist/_internal/components/navigation/SectionNav/SectionNav.primary.js +4 -4
  42. package/dist/_internal/components/navigation/SectionNav/SectionNav.rail.js +5 -5
  43. package/dist/_internal/components/navigation/SectionNav/SectionNav.railCreate.js +4 -4
  44. package/dist/_internal/components/navigation/SectionNav/SectionNav.sheet.js +4 -4
  45. package/dist/_internal/components/navigation/index.js +9 -9
  46. package/dist/_internal/en-US.data-display.js +1 -1
  47. package/dist/_internal/pt-BR.data-display.js +1 -1
  48. package/dist/_internal/user-avatar/user-avatar.js +3 -3
  49. package/dist/charts.js +8 -8
  50. package/dist/{chunk-RBHBJDOZ.js → chunk-3FMWQQW6.js} +5 -5
  51. package/dist/chunk-3FMWQQW6.js.map +1 -0
  52. package/dist/{chunk-MKAA3YIJ.js → chunk-3K7WN2PO.js} +3 -3
  53. package/dist/{chunk-GI24X7XA.js → chunk-4PPNCZWY.js} +3 -3
  54. package/dist/{chunk-573XC4HK.js → chunk-4QKS5Y35.js} +2 -2
  55. package/dist/{chunk-KX75HM5U.js → chunk-5YDS6HO3.js} +7 -2
  56. package/dist/{chunk-KX75HM5U.js.map → chunk-5YDS6HO3.js.map} +1 -1
  57. package/dist/{chunk-N4MR4EMC.js → chunk-6D2PFC5C.js} +2 -2
  58. package/dist/{chunk-QVWNK4JO.js → chunk-6GPNZSAE.js} +19 -2
  59. package/dist/chunk-6GPNZSAE.js.map +1 -0
  60. package/dist/{chunk-LJKWWXZD.js → chunk-6OSUK2C7.js} +28 -22
  61. package/dist/chunk-6OSUK2C7.js.map +1 -0
  62. package/dist/{chunk-ICSXPZXT.js → chunk-6QBT5TPS.js} +2 -2
  63. package/dist/{chunk-A6EUQDRK.js → chunk-ARJIKW56.js} +4 -2
  64. package/dist/chunk-ARJIKW56.js.map +1 -0
  65. package/dist/{chunk-53ACGKBW.js → chunk-EDBP62WG.js} +3 -3
  66. package/dist/{chunk-YXIVQFNW.js → chunk-EWIKSTJV.js} +4 -4
  67. package/dist/{chunk-LWZ2K225.js → chunk-FXZUVZON.js} +6 -6
  68. package/dist/chunk-G6EJLEVV.js +75 -0
  69. package/dist/chunk-G6EJLEVV.js.map +1 -0
  70. package/dist/{chunk-IK2ZVV3M.js → chunk-GK7JNSMK.js} +2 -2
  71. package/dist/{chunk-HFBQCJNP.js → chunk-HCYRCU4W.js} +2 -2
  72. package/dist/{chunk-BJMNAPKH.js → chunk-HH7PM5HT.js} +10 -22
  73. package/dist/chunk-HH7PM5HT.js.map +1 -0
  74. package/dist/{chunk-7AAJYWC3.js → chunk-HPO7PB4F.js} +2 -2
  75. package/dist/{chunk-WF3P7GE5.js → chunk-I3CQBEKS.js} +2 -2
  76. package/dist/{chunk-RREWYOKS.js → chunk-IL4FCC54.js} +2 -2
  77. package/dist/{chunk-7M3DRP7Q.js → chunk-ILNO4ZJ6.js} +3 -3
  78. package/dist/{chunk-R6SBP5M5.js → chunk-JVOEVTCZ.js} +4 -2
  79. package/dist/chunk-JVOEVTCZ.js.map +1 -0
  80. package/dist/{chunk-2CJZLL5Y.js → chunk-NHVL2QPG.js} +2 -1
  81. package/dist/{chunk-2CJZLL5Y.js.map → chunk-NHVL2QPG.js.map} +1 -1
  82. package/dist/{chunk-45PGSVOH.js → chunk-NTJUAPJM.js} +10 -8
  83. package/dist/chunk-NTJUAPJM.js.map +1 -0
  84. package/dist/{chunk-EUPUEMFX.js → chunk-PC4H5LVB.js} +7 -7
  85. package/dist/{chunk-KEKOPD43.js → chunk-PQ7RWH7L.js} +4 -2
  86. package/dist/chunk-PQ7RWH7L.js.map +1 -0
  87. package/dist/{chunk-HRMB72E4.js → chunk-QHP5PZNC.js} +2 -1
  88. package/dist/{chunk-HRMB72E4.js.map → chunk-QHP5PZNC.js.map} +1 -1
  89. package/dist/{chunk-GNBCSTXF.js → chunk-QKAYXAQE.js} +6 -6
  90. package/dist/{chunk-GNBCSTXF.js.map → chunk-QKAYXAQE.js.map} +1 -1
  91. package/dist/{chunk-TZFBJ47T.js → chunk-SFLNHCA2.js} +39 -15
  92. package/dist/chunk-SFLNHCA2.js.map +1 -0
  93. package/dist/{chunk-OBMPE6PW.js → chunk-SSDYEOU4.js} +5 -5
  94. package/dist/{chunk-I6ESCBY3.js → chunk-TF27Z27K.js} +2 -2
  95. package/dist/{chunk-JF5LQOGB.js → chunk-U47KRLEW.js} +57 -45
  96. package/dist/chunk-U47KRLEW.js.map +1 -0
  97. package/dist/chunk-V4V2N6YJ.js +55 -0
  98. package/dist/chunk-V4V2N6YJ.js.map +1 -0
  99. package/dist/{chunk-C67FDYG7.js → chunk-W7N4ORCV.js} +16 -6
  100. package/dist/chunk-W7N4ORCV.js.map +1 -0
  101. package/dist/{chunk-JL77BSOL.js → chunk-WBDQSBLV.js} +2 -2
  102. package/dist/{chunk-G76BNXWE.js → chunk-XW5SEW3H.js} +6 -6
  103. package/dist/{chunk-46ZATLQV.js → chunk-YIKFYWKD.js} +3 -3
  104. package/dist/{chunk-4JBS6NOT.js → chunk-ZWBGQYVO.js} +35 -6
  105. package/dist/chunk-ZWBGQYVO.js.map +1 -0
  106. package/dist/{chunk-VWW2EXH7.js → chunk-ZYJZHXFU.js} +4 -4
  107. package/dist/data-display/Avatar.js +2 -2
  108. package/dist/data-display/Badge.js +2 -2
  109. package/dist/data-display/CardKit.js +10 -10
  110. package/dist/data-display/Carousel.js +2 -2
  111. package/dist/data-display/Chart.js +8 -8
  112. package/dist/data-display/DataGrid.js +2 -2
  113. package/dist/data-display/DataViews.js +25 -23
  114. package/dist/en-US.js +1 -1
  115. package/dist/layout/ContentToolbar.js +1 -1
  116. package/dist/locales.js +2 -2
  117. package/dist/navigation/SectionNav.js +9 -9
  118. package/dist/pt-BR.js +1 -1
  119. package/dist/types/components/data-display/Chart/Chart.types.d.ts +5 -0
  120. package/dist/types/components/data-display/Chart/Chart.types.d.ts.map +1 -1
  121. package/dist/types/components/data-display/Chart/chart-context.d.ts.map +1 -1
  122. package/dist/types/components/data-display/Chart/chart-format.d.ts +14 -0
  123. package/dist/types/components/data-display/Chart/chart-format.d.ts.map +1 -1
  124. package/dist/types/components/data-display/Chart/chart-spec.d.ts.map +1 -1
  125. package/dist/types/components/data-display/DataViews/DataViewsTableBase.d.ts.map +1 -1
  126. package/dist/types/components/data-display/DataViews/base-list-card-geometry.d.ts +29 -1
  127. package/dist/types/components/data-display/DataViews/base-list-card-geometry.d.ts.map +1 -1
  128. package/dist/types/components/data-display/DataViews/base-list-card-layout.d.ts +46 -0
  129. package/dist/types/components/data-display/DataViews/base-list-card-layout.d.ts.map +1 -0
  130. package/dist/types/components/data-display/DataViews/base-list-card-slots.d.ts +5 -2
  131. package/dist/types/components/data-display/DataViews/base-list-card-slots.d.ts.map +1 -1
  132. package/dist/types/components/data-display/DataViews/base-list-card.d.ts +10 -1
  133. package/dist/types/components/data-display/DataViews/base-list-card.d.ts.map +1 -1
  134. package/dist/types/components/data-display/DataViews/data-views-copy.d.ts +7 -0
  135. package/dist/types/components/data-display/DataViews/data-views-copy.d.ts.map +1 -1
  136. package/dist/types/components/data-display/DataViews/data-views-grid-parts.d.ts.map +1 -1
  137. package/dist/types/components/data-display/DataViews/data-views-selection-extra.d.ts +2 -0
  138. package/dist/types/components/data-display/DataViews/data-views-selection-extra.d.ts.map +1 -1
  139. package/dist/types/components/data-display/DataViews/data-views-shell-toolbar.d.ts +3 -1
  140. package/dist/types/components/data-display/DataViews/data-views-shell-toolbar.d.ts.map +1 -1
  141. package/dist/types/components/data-display/DataViews/data-views-toolbar.d.ts +2 -0
  142. package/dist/types/components/data-display/DataViews/data-views-toolbar.d.ts.map +1 -1
  143. package/dist/types/components/data-display/DataViews/data-views-url-echo.d.ts +47 -0
  144. package/dist/types/components/data-display/DataViews/data-views-url-echo.d.ts.map +1 -0
  145. package/dist/types/components/data-display/DataViews/list-card-rails.d.ts +17 -2
  146. package/dist/types/components/data-display/DataViews/list-card-rails.d.ts.map +1 -1
  147. package/dist/types/components/layout/ContentToolbar/ContentToolbar.d.ts +3 -2
  148. package/dist/types/components/layout/ContentToolbar/ContentToolbar.d.ts.map +1 -1
  149. package/dist/types/components/layout/ContentToolbar/ContentToolbar.types.d.ts +14 -0
  150. package/dist/types/components/layout/ContentToolbar/ContentToolbar.types.d.ts.map +1 -1
  151. package/dist/types/en-US.data-display.d.ts.map +1 -1
  152. package/dist/types/pt-BR.data-display.d.ts.map +1 -1
  153. package/dist/user-avatar.js +3 -3
  154. package/package.json +1 -1
  155. package/src/components/data-display/Chart/Chart.md +5 -1
  156. package/src/components/data-display/Chart/Chart.types.ts +5 -0
  157. package/src/components/data-display/Chart/chart-context.ts +21 -1
  158. package/src/components/data-display/Chart/chart-format.ts +31 -0
  159. package/src/components/data-display/Chart/chart-renderers.tsx +1 -1
  160. package/src/components/data-display/Chart/chart-spec.ts +2 -1
  161. package/src/components/data-display/DataViews/DataViewsTableBase.tsx +7 -36
  162. package/src/components/data-display/DataViews/base-list-card-geometry.tsx +114 -40
  163. package/src/components/data-display/DataViews/base-list-card-layout.tsx +104 -0
  164. package/src/components/data-display/DataViews/base-list-card-slots.tsx +47 -3
  165. package/src/components/data-display/DataViews/base-list-card.tsx +65 -68
  166. package/src/components/data-display/DataViews/data-views-copy.ts +7 -0
  167. package/src/components/data-display/DataViews/data-views-grid-parts.tsx +2 -1
  168. package/src/components/data-display/DataViews/data-views-selection-extra.ts +10 -1
  169. package/src/components/data-display/DataViews/data-views-shell-toolbar.tsx +4 -0
  170. package/src/components/data-display/DataViews/data-views-toolbar.tsx +4 -0
  171. package/src/components/data-display/DataViews/data-views-url-echo.ts +134 -0
  172. package/src/components/data-display/DataViews/list-card-rails.tsx +22 -6
  173. package/src/components/layout/ContentToolbar/ContentToolbar.md +5 -2
  174. package/src/components/layout/ContentToolbar/ContentToolbar.tsx +51 -10
  175. package/src/components/layout/ContentToolbar/ContentToolbar.types.ts +14 -0
  176. package/src/en-US.data-display.ts +1 -0
  177. package/src/pt-BR.data-display.ts +1 -0
  178. package/dist/chunk-45PGSVOH.js.map +0 -1
  179. package/dist/chunk-4JBS6NOT.js.map +0 -1
  180. package/dist/chunk-A6EUQDRK.js.map +0 -1
  181. package/dist/chunk-BJMNAPKH.js.map +0 -1
  182. package/dist/chunk-C67FDYG7.js.map +0 -1
  183. package/dist/chunk-JF5LQOGB.js.map +0 -1
  184. package/dist/chunk-KEKOPD43.js.map +0 -1
  185. package/dist/chunk-LJKWWXZD.js.map +0 -1
  186. package/dist/chunk-QVWNK4JO.js.map +0 -1
  187. package/dist/chunk-R6SBP5M5.js.map +0 -1
  188. package/dist/chunk-RBHBJDOZ.js.map +0 -1
  189. package/dist/chunk-TZFBJ47T.js.map +0 -1
  190. /package/dist/{chunk-MKAA3YIJ.js.map → chunk-3K7WN2PO.js.map} +0 -0
  191. /package/dist/{chunk-GI24X7XA.js.map → chunk-4PPNCZWY.js.map} +0 -0
  192. /package/dist/{chunk-573XC4HK.js.map → chunk-4QKS5Y35.js.map} +0 -0
  193. /package/dist/{chunk-N4MR4EMC.js.map → chunk-6D2PFC5C.js.map} +0 -0
  194. /package/dist/{chunk-ICSXPZXT.js.map → chunk-6QBT5TPS.js.map} +0 -0
  195. /package/dist/{chunk-53ACGKBW.js.map → chunk-EDBP62WG.js.map} +0 -0
  196. /package/dist/{chunk-YXIVQFNW.js.map → chunk-EWIKSTJV.js.map} +0 -0
  197. /package/dist/{chunk-LWZ2K225.js.map → chunk-FXZUVZON.js.map} +0 -0
  198. /package/dist/{chunk-IK2ZVV3M.js.map → chunk-GK7JNSMK.js.map} +0 -0
  199. /package/dist/{chunk-HFBQCJNP.js.map → chunk-HCYRCU4W.js.map} +0 -0
  200. /package/dist/{chunk-7AAJYWC3.js.map → chunk-HPO7PB4F.js.map} +0 -0
  201. /package/dist/{chunk-WF3P7GE5.js.map → chunk-I3CQBEKS.js.map} +0 -0
  202. /package/dist/{chunk-RREWYOKS.js.map → chunk-IL4FCC54.js.map} +0 -0
  203. /package/dist/{chunk-7M3DRP7Q.js.map → chunk-ILNO4ZJ6.js.map} +0 -0
  204. /package/dist/{chunk-EUPUEMFX.js.map → chunk-PC4H5LVB.js.map} +0 -0
  205. /package/dist/{chunk-OBMPE6PW.js.map → chunk-SSDYEOU4.js.map} +0 -0
  206. /package/dist/{chunk-I6ESCBY3.js.map → chunk-TF27Z27K.js.map} +0 -0
  207. /package/dist/{chunk-JL77BSOL.js.map → chunk-WBDQSBLV.js.map} +0 -0
  208. /package/dist/{chunk-G76BNXWE.js.map → chunk-XW5SEW3H.js.map} +0 -0
  209. /package/dist/{chunk-46ZATLQV.js.map → chunk-YIKFYWKD.js.map} +0 -0
  210. /package/dist/{chunk-VWW2EXH7.js.map → chunk-ZYJZHXFU.js.map} +0 -0
@@ -206,16 +206,32 @@ export const RAIL_COUNT = 8;
206
206
  */
207
207
  const CELL_FIXED_RAILS = 4;
208
208
 
209
- /** Tracks for a cell-configured row: gutters, leading, the cells, then the menu. */
210
- export function cellRailsTemplate(cells: readonly string[]): string {
209
+ /**
210
+ * Tracks for a cell-configured row: gutters, leading, the cells, then the menu.
211
+ *
212
+ * `gutters` says which of the three head gutters RENDER. A group reserves all
213
+ * three (the default), so every row spans the same tracks. A standalone row
214
+ * renders a gutter only when it uses it, and a track whose slot renders nothing
215
+ * is not a reserved gap: grid auto-placement fills it with the NEXT slot. So the
216
+ * checkbox landed in the disclosure track, the glyph in the drag track, and
217
+ * every cell two tracks early, in a column sized for something else. The named-
218
+ * slot layout already drops absent gutters ({@link railsTemplateFor}); this is
219
+ * the same rule for configured cells.
220
+ */
221
+ export function cellRailsTemplate(
222
+ cells: readonly string[],
223
+ gutters: { disclose: boolean; drag: boolean; select: boolean } = { disclose: true, drag: true, select: true },
224
+ ): string {
211
225
  return [
212
- DEFAULT_RAILS.disclose,
213
- DEFAULT_RAILS.drag,
214
- DEFAULT_RAILS.select,
226
+ gutters.disclose ? DEFAULT_RAILS.disclose : null,
227
+ gutters.drag ? DEFAULT_RAILS.drag : null,
228
+ gutters.select ? DEFAULT_RAILS.select : null,
215
229
  DEFAULT_RAILS.leading,
216
230
  ...cells,
217
231
  DEFAULT_RAILS.actions,
218
- ].join(" ");
232
+ ]
233
+ .filter((rail): rail is string => rail != null)
234
+ .join(" ");
219
235
  }
220
236
 
221
237
  /** How many tracks such a row spans — the fixed head/tail plus one per cell. */
@@ -13,8 +13,10 @@ pages and projects.
13
13
  ```
14
14
 
15
15
  - **Left cluster** — always shows **Select All**. Once `hasSelection` is true it
16
- adds **Clear All**, an "N items selected" count, and two optional slots:
17
- `selectionExtra` then `actions`.
16
+ adds **Clear All**, the selection count, and two optional slots:
17
+ `selectionExtra` then `actions`. The count's words come from the required
18
+ `selectedCountLabel(count)` ("1 selecionado", "3 selecionados"); the
19
+ package ships no default, and DataViews feeds it `copy.selection.selectedCount`.
18
20
  - **`selectionExtra` vs `actions`** — `actions` is what HAPPENS to the selection
19
21
  (delete, export, send). `selectionExtra` is what the selection IS: the
20
22
  "select all N matching the filter" widening a paginated list needs once its
@@ -48,6 +50,7 @@ import {
48
50
  <ContentToolbar
49
51
  hasSelection={selected.size > 0}
50
52
  selectedCount={selected.size}
53
+ selectedCountLabel={(n) => `${n} ${n === 1 ? 'selecionado' : 'selecionados'}`}
51
54
  selectAll={selectAll}
52
55
  clearSelection={clear}
53
56
  actions={<DeleteButton />}
@@ -27,6 +27,8 @@ type SelectionClusterProps = Pick<
27
27
  ContentToolbarProps,
28
28
  | 'hasSelection'
29
29
  | 'selectedCount'
30
+ | 'selectedCountLabel'
31
+ | 'allSelected'
30
32
  | 'selectAll'
31
33
  | 'clearSelection'
32
34
  | 'actions'
@@ -39,10 +41,42 @@ type SelectionClusterProps = Pick<
39
41
  | 'clearAllText'
40
42
  >;
41
43
 
44
+ /**
45
+ * The phone's select-all box. Checked only when everything is ticked and
46
+ * partial while some is, when the host says which (`allSelected`) — the same
47
+ * reading as the table's header checkbox. A partial box selects the rest, as
48
+ * the header does; a full one clears.
49
+ */
50
+ function SelectAllBox({
51
+ hasSelection,
52
+ allSelected,
53
+ selectAll,
54
+ clearSelection,
55
+ selectAllTestId,
56
+ selectAllLabel,
57
+ }: Pick<
58
+ ContentToolbarProps,
59
+ 'hasSelection' | 'allSelected' | 'selectAll' | 'clearSelection' | 'selectAllTestId' | 'selectAllLabel'
60
+ >): React.JSX.Element {
61
+ return (
62
+ <Checkbox
63
+ size="small"
64
+ checked={allSelected ?? hasSelection}
65
+ indeterminate={hasSelection && allSelected === false}
66
+ onChange={() => (hasSelection && allSelected !== false ? clearSelection() : selectAll())}
67
+ data-testid={`${selectAllTestId}-checkbox`}
68
+ inputProps={{ 'aria-label': selectAllLabel }}
69
+ sx={{ p: 0.5, display: { xs: 'inline-flex', md: 'none' } }}
70
+ />
71
+ );
72
+ }
73
+
42
74
  /** The left cluster: Select All + (when selecting) Clear All / count / actions. */
43
75
  function SelectionCluster({
44
76
  hasSelection,
77
+ allSelected,
45
78
  selectedCount,
79
+ selectedCountLabel,
46
80
  selectAll,
47
81
  clearSelection,
48
82
  actions,
@@ -95,17 +129,18 @@ function SelectionCluster({
95
129
  >
96
130
  {selectAllText}
97
131
  </Button>
98
- <Checkbox
99
- size="small"
100
- checked={hasSelection}
101
- onChange={(event) => (event.target.checked ? selectAll() : clearSelection())}
102
- data-testid={`${selectAllTestId}-checkbox`}
103
- inputProps={{ 'aria-label': selectAllLabel }}
104
- sx={{ p: 0.5, display: { xs: 'inline-flex', md: 'none' } }}
132
+ <SelectAllBox
133
+ hasSelection={hasSelection}
134
+ allSelected={allSelected}
135
+ selectAll={selectAll}
136
+ clearSelection={clearSelection}
137
+ selectAllTestId={selectAllTestId}
138
+ selectAllLabel={selectAllLabel}
105
139
  />
106
140
  {hasSelection ? (
107
141
  <SelectionState
108
142
  selectedCount={selectedCount}
143
+ selectedCountLabel={selectedCountLabel}
109
144
  clearSelection={clearSelection}
110
145
  clearAllTestId={clearAllTestId}
111
146
  clearAllText={clearAllText}
@@ -128,13 +163,14 @@ function SelectionCluster({
128
163
  */
129
164
  function SelectionState({
130
165
  selectedCount,
166
+ selectedCountLabel,
131
167
  clearSelection,
132
168
  clearAllTestId,
133
169
  clearAllText,
134
170
  selectionExtra,
135
171
  }: Pick<
136
172
  ContentToolbarProps,
137
- 'selectedCount' | 'clearSelection' | 'clearAllTestId' | 'clearAllText' | 'selectionExtra'
173
+ 'selectedCount' | 'selectedCountLabel' | 'clearSelection' | 'clearAllTestId' | 'clearAllText' | 'selectionExtra'
138
174
  >): React.JSX.Element {
139
175
  return (
140
176
  <>
@@ -154,7 +190,7 @@ function SelectionState({
154
190
  data-testid="selected-count-indicator"
155
191
  sx={{ fontSize: sxRem(14), color: 'text.secondary', whiteSpace: 'nowrap', flexShrink: 0 }}
156
192
  >
157
- {selectedCount} {selectedCount === 1 ? 'item' : 'items'} selected
193
+ {selectedCountLabel(selectedCount)}
158
194
  </Typography>
159
195
  {selectionExtra !== undefined && (
160
196
  <>
@@ -246,7 +282,7 @@ function BrowsingClusters({
246
282
  /**
247
283
  * Shared toolbar for content pages (Favorites, Personal Space, Recents, …). The
248
284
  * left cluster owns selection chrome — **Select All**, and once items are
249
- * selected, **Clear All** + an "N items selected" count + an optional `actions`
285
+ * selected, **Clear All** + the count (`selectedCountLabel`) + an optional `actions`
250
286
  * slot. The right cluster is a free `rightControls` slot for page-specific
251
287
  * controls (ViewSelector, SortByDropdown, MultiSelectDropdown, FilterTrigger).
252
288
  *
@@ -259,6 +295,7 @@ function BrowsingClusters({
259
295
  * <ContentToolbar
260
296
  * hasSelection={selected.size > 0}
261
297
  * selectedCount={selected.size}
298
+ * selectedCountLabel={(n) => `${n} ${n === 1 ? 'selecionado' : 'selecionados'}`}
262
299
  * selectAll={selectAll}
263
300
  * clearSelection={clear}
264
301
  * rightControls={
@@ -274,7 +311,9 @@ function BrowsingClusters({
274
311
  */
275
312
  export function ContentToolbar({
276
313
  hasSelection,
314
+ allSelected,
277
315
  selectedCount,
316
+ selectedCountLabel,
278
317
  selectAll,
279
318
  clearSelection,
280
319
  rightControls,
@@ -316,7 +355,9 @@ export function ContentToolbar({
316
355
  selectAllText={selectAllText}
317
356
  clearAllText={clearAllText}
318
357
  hasSelection={hasSelection}
358
+ allSelected={allSelected}
319
359
  selectedCount={selectedCount}
360
+ selectedCountLabel={selectedCountLabel}
320
361
  selectAll={selectAll}
321
362
  clearSelection={clearSelection}
322
363
  actions={actions}
@@ -17,6 +17,20 @@ export interface ContentToolbarProps {
17
17
  hasSelection: boolean;
18
18
  /** Number of currently selected items. */
19
19
  selectedCount: number;
20
+ /**
21
+ * The words for that count — "1 selecionado", "3 selecionados".
22
+ * A function because the noun agrees with the number. REQUIRED: this package
23
+ * ships no default copy, and the English it used to hardcode here was the one
24
+ * string on a pt-BR admin list a host could not replace (FUT-1443).
25
+ */
26
+ selectedCountLabel: (count: number) => string;
27
+ /**
28
+ * Whether EVERYTHING the select-all box covers is selected. When given, the
29
+ * box reads checked only then, and partial (indeterminate) while just some
30
+ * rows are — as the table's own header checkbox does. Omitted, it keeps
31
+ * reading checked for any selection.
32
+ */
33
+ allSelected?: boolean;
20
34
  /** Select every item on the page. */
21
35
  selectAll: () => void;
22
36
  /** Clear the current selection. */
@@ -230,6 +230,7 @@ export const EN_US_DATA_VIEWS_COPY: DataViewsCopy = {
230
230
  clearSelection: "Clear selection",
231
231
  selectAll: "Select all",
232
232
  onThisPage: (count) => `${count} on this page`,
233
+ selectedCount: (count) => `${count} ${count === 1 ? "item selected" : "items selected"}`,
233
234
  selectRow: "Select",
234
235
  expandRow: "Expand details",
235
236
  collapseRow: "Collapse details",
@@ -222,6 +222,7 @@ export const PT_BR_DATA_VIEWS_COPY: DataViewsCopy = {
222
222
  clearSelection: "Limpar seleção",
223
223
  selectAll: "Selecionar tudo",
224
224
  onThisPage: (count) => `${count} nesta página`,
225
+ selectedCount: (count) => `${count} ${count === 1 ? "selecionado" : "selecionados"}`,
225
226
  selectRow: "Selecionar",
226
227
  expandRow: "Expandir detalhes",
227
228
  collapseRow: "Recolher detalhes",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/DataViews/data-views-grid-parts.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\n\nimport { TableFilter } from \"../../layout/TableFilter\";\nimport { Stack } from \"../../../mui/Stack\";\n\nimport {\n DataViewsLayoutProvider,\n useDataViewsLayout,\n type DataViewsLayout,\n} from \"./data-views-layout-context\";\nimport { FilterDialog, GridFilterPanel } from \"./data-views-filter-panel\";\nimport { GridMain } from \"./data-views-grid-bodies\";\nimport type { ListGroupConfig } from \"./list-card-rails\";\nimport { InlineFilterControls } from \"./data-views-inline-bar\";\nimport { toOverflowFields, useFilterOverflow, type OverflowSplit } from \"./data-views-overflow\";\nimport { GridHeaderRow } from \"./data-views-header-row\";\nimport { resolveSelectionExtra, type SelectionExtraRender } from \"./data-views-selection-extra\";\nimport { ShellToolbar } from \"./data-views-shell-toolbar\";\nimport type { DisplayPanelView } from \"./data-views-display-panel\";\nimport type { DataViewExport } from \"./data-views-export\";\nimport { useDataViewsCopy } from \"./data-views-copy-context\";\nimport { DataViewsEmpty } from \"./data-views-empty\";\nimport { DataViewsPagination } from \"./data-views-pagination\";\nimport type { BoardConfig } from \"./DataViewsBoard\";\nimport { type ScopeConfig } from \"./data-views-scopes\";\nimport { ScopeTabsSlot } from \"./data-views-scope-tabs\";\nimport { togglePillValues } from \"./data-views-grid-helpers\";\nimport type {\n DataViewCardSelection,\n FilterFieldConfig,\n RangeFieldConfig,\n RangeValue,\n RowAction,\n} from \"./data-views-types\";\nimport type { DataViewRowDetail } from \"./data-views-row-detail\";\nimport type { DataViewsController } from \"./use-data-views-state\";\n\n/* ── Layout ⇄ view-state mirror ──────────────────────────────────────────── */\n\n/**\n * Mirrors the LIVE layout back into the view state, so saving a view captures\n * the layout the user is actually looking at.\n *\n * A component rather than a callback prop because only something INSIDE the\n * provider can read the layout, and only the controller can write the state.\n * The `stored !== layout` guard is what makes it idempotent: `c` is rebuilt on\n * every render, so an unguarded effect here would patch → re-render → patch.\n *\n * It re-fires when `stored` changes too, which is the case that matters after\n * applying a saved view: `appliedState` REPLACES the state, so a view saved\n * before layouts were captured clears `state.layout`, and the mirror puts the\n * current one back rather than leaving the next save with nothing to store.\n */\nfunction LayoutStateSync<T extends Record<string, unknown>>({\n c,\n}: {\n c: DataViewsController<T>;\n}): null {\n const { layout } = useDataViewsLayout();\n const stored = c.state.layout;\n useEffect(() => {\n if (stored !== layout) c.patch({ layout });\n // `c` is intentionally out of the deps — see the guard above.\n }, [layout, stored]);\n return null;\n}\n\n/* ── Shell (composes toolbar + body + panel) ─────────────────────────────── */\n\n/** The shared filter-surface props consumed by the inline bar, panel, and modal. */\ninterface FilterSurfaceProps<T extends Record<string, unknown>> {\n testIdPrefix: string;\n search: string;\n fields: FilterFieldConfig<T>[];\n rangeFields: RangeFieldConfig<T>[];\n pills: Record<string, string[]>;\n ranges: Record<string, RangeValue>;\n onSearchChange: (value: string) => void;\n onTogglePill: (fieldId: string, value: string, checked: boolean) => void;\n onChangeRange: (fieldId: string, range: RangeValue) => void;\n onClearField: (fieldId: string) => void;\n onClearAll: () => void;\n}\n\n/**\n * Derives the responsive filter state (which surface to show at this width) and\n * the filter-mutation handlers from the controller — pulled out of `GridShell`\n * so the component body stays under the size/complexity budget.\n */\n/** Grouped rather than positional: the list had grown past readability. */\ninterface GridShellFiltersArgs<T extends Record<string, unknown>> {\n c: DataViewsController<T>;\n inlineFilters: boolean;\n fields: FilterFieldConfig<T>[];\n rangeFields: RangeFieldConfig<T>[];\n testIdPrefix: string;\n alwaysShowSearch: boolean;\n /** Is \"Exportar\" on the bar? Half the right cluster's cost when it is not. */\n hasExport: boolean;\n}\n\nfunction useGridShellFilters<T extends Record<string, unknown>>({\n c,\n inlineFilters,\n fields,\n rangeFields,\n testIdPrefix,\n alwaysShowSearch,\n hasExport,\n}: GridShellFiltersArgs<T>): {\n showInline: boolean;\n useModal: boolean;\n inlineVisible: boolean;\n filterProps: FilterSurfaceProps<T>;\n split: OverflowSplit<T>;\n onControlOpenChange: (open: boolean) => void;\n} {\n const { state } = c;\n // How many filter controls are open. A COUNT, not a flag: closing one popover\n // by opening another overlaps, and a boolean would unfreeze mid-handover.\n const [openControls, setOpenControls] = useState(0);\n // ONE measurement for the whole shell: the filter row decides which controls\n // it can keep, and the TOOLBAR needs the same answer to drop its labels.\n // Measuring twice would let the two disagree at the crossover width.\n const split = useFilterOverflow(\n toOverflowFields(fields, rangeFields),\n state.pills,\n c.ranges,\n openControls > 0,\n hasExport,\n );\n // THE BAR RENDERS AT EVERY WIDTH. It used to be swapped for a full-screen\n // filter MODAL below `lg`, which was the responsive strategy before the\n // measured ladder existed — and the two now do the same job, badly together:\n // the modal took the bar away at 1199px, and with it the very degradation\n // (labels off, search collapsed, filters into \"Mais\") that exists to make a\n // narrow bar work. So a 900px window got no bar and no ladder, and the\n // operator lost the search entirely rather than gaining a compact one.\n //\n // The ladder is measured, so it already covers every width the modal did.\n const showInline = inlineFilters;\n const useModal = false;\n const inlineVisible =\n showInline &&\n (alwaysShowSearch || fields.length > 0 || rangeFields.length > 0 || state.search !== \"\");\n const filterProps: FilterSurfaceProps<T> = {\n testIdPrefix,\n search: state.search,\n fields,\n rangeFields,\n pills: state.pills,\n ranges: c.ranges,\n onSearchChange: (value) => c.patch({ search: value }),\n // Updater, never the render's `state` — see {@link DataViewStatePatch}.\n onTogglePill: (fieldId, value, checked) =>\n c.patch(({ pills }) => ({ pills: { ...pills, [fieldId]: togglePillValues(pills[fieldId], value, checked) } })),\n onChangeRange: (fieldId, range) => c.patch({ ranges: { ...c.ranges, [fieldId]: range } }),\n onClearField: (fieldId) => c.patch({ pills: { ...state.pills, [fieldId]: [] } }),\n onClearAll: () => c.patch({ search: \"\", pills: {}, ranges: {} }),\n };\n return {\n showInline,\n useModal,\n inlineVisible,\n filterProps,\n split,\n onControlOpenChange: (open) =>\n setOpenControls((count) => Math.max(0, count + (open ? 1 : -1))),\n };\n}\n\ninterface GridShellProps<T extends Record<string, unknown>> {\n c: DataViewsController<T>;\n rows: T[];\n fields: FilterFieldConfig<T>[];\n rangeFields: RangeFieldConfig<T>[];\n getRowId: (row: T) => string | number;\n testIdPrefix: string;\n dataTestId?: string;\n emptyState?: React.ReactNode;\n toolbarRightSlot?: React.ReactNode;\n rowActions?: RowAction<T>[];\n bulkActions?: (selectedRows: T[], clearSelection: () => void) => React.ReactNode;\n /** A widening control beside the selection count — see `resolveSelectionExtra`. */\n selectionExtra?: SelectionExtraRender<T>;\n /** Opt-in \"Grade\" (cards) layout: renders each row as an entity-supplied card.\n * Omit ⇒ table only (no layout toggle). */\n renderCard?: (row: T, selection: DataViewCardSelection) => React.ReactNode;\n /**\n * Opt-in \"Quadro\" (board) layout. Needs `renderCard` too — the board reuses\n * the entity's card, so a board config without one simply offers no board\n * rather than failing: that is a config gap, not a runtime error.\n */\n board?: BoardConfig<T>;\n /** Opt-in \"Lista\" layout: one full-width, entity-rendered row per record. */\n renderListRow?: (row: T, selection: DataViewCardSelection) => React.ReactNode;\n /** The Lista's shared columns, so its rows line up by construction. */\n listGroup?: ListGroupConfig<T>;\n /** Opt-in expandable rows, drawn by the table layout only. */\n rowDetail?: DataViewRowDetail<T>;\n /** The page-level partition rendered as tabs under the toolbar. */\n scopes?: ScopeConfig[];\n /**\n * The row field the scopes partition by. Compared against the board's\n * `groupBy` so the two are not shown as the same partition twice.\n */\n scopeFieldId?: string;\n /** Per-sort-field value kind, so directions read in the column's own terms. */\n sortKinds?: Record<string, string>;\n /** The saved-view chrome bracketing the Exibir panel. */\n displayView?: DisplayPanelView;\n /** Injected export — the host re-queries; the grid never fetches. */\n exportConfig?: DataViewExport;\n /** Page title in the grid's own header row, above the scopes + toolbar. */\n title?: string;\n /** Primary page actions rendered at the header row's right. */\n headerActions?: React.ReactNode;\n /** Which layout to show first when the user has expressed no preference (default \"table\"). */\n defaultLayout?: DataViewsLayout;\n /** Pin to `defaultLayout`, ignoring the remembered preference (stories/docs). */\n ignoreStoredLayout?: boolean;\n /**\n * Opt into the responsive inline filter UX: a collapsible filter row below the\n * toolbar on wide screens and a modal on narrow ones. When false (default),\n * keep the classic slide-in filter panel opened by the \"Filtros\" button.\n */\n inlineFilters?: boolean;\n /**\n * Keep the inline search box on screen even with no filter fields and no\n * active search. Without it a grid whose only filter IS the search (`fields`\n * empty) can never OFFER one: the row renders only once a search exists, so\n * the operator would have to hand-edit the URL to start one. Default false —\n * every grid that ships filter fields already shows the row.\n */\n alwaysShowSearch?: boolean;\n}\n\n/** The scrollable content region: scope tabs, toolbar, filter bar, body, pager. */\nfunction ShellStack<T extends Record<string, unknown>>({\n props,\n filters,\n}: {\n props: GridShellProps<T>;\n filters: ReturnType<typeof useGridShellFilters<T>>;\n}): React.JSX.Element {\n const copy = useDataViewsCopy();\n const { c, testIdPrefix, dataTestId, scopes = [], emptyState, inlineFilters = false } = props;\n const { showInline, useModal, inlineVisible, filterProps, split, onControlOpenChange } = filters;\n // The grid renders the FILTERED empty state itself — it is the only party\n // that knows a filter is applied. See {@link DataViewsEmpty}.\n const body = (\n <DataViewsEmpty\n filtered={c.activeFilterCount > 0 || c.state.search !== \"\"}\n onClearFilters={() => c.patch({ search: \"\", pills: {}, ranges: {} })}\n emptyState={emptyState}\n testIdPrefix={testIdPrefix}\n />\n );\n return (\n <TableFilter\n copy={copy.tableFilter} open={c.filterOpen} onOpenChange={c.setFilterOpen}\n hasActiveFilters={c.activeFilterCount > 0}\n >\n <Stack spacing={0} data-testid={dataTestId ? `${dataTestId}-container` : undefined}>\n <GridHeaderRow title={props.title} headerActions={props.headerActions} testIdPrefix={testIdPrefix} />\n <ShellToolbar\n c={c}\n rows={props.rows}\n sortKinds={props.sortKinds}\n displayView={props.displayView}\n exportConfig={props.exportConfig}\n filterControls={\n inlineVisible ? (\n <InlineFilterControls\n {...filterProps} split={split} activeFilterCount={c.activeFilterCount}\n onControlOpenChange={onControlOpenChange}\n />\n ) : undefined\n }\n barRef={split.barRef}\n testIdPrefix={testIdPrefix}\n rowActions={props.rowActions}\n bulkActions={props.bulkActions}\n selectionExtra={resolveSelectionExtra(props)}\n toolbarRightSlot={props.toolbarRightSlot}\n compactControls={showInline && split.compactControls}\n counterHidden={showInline && split.counterHidden}\n showInline={showInline}\n />\n <ScopeTabsSlot\n scopes={scopes} scopeFieldId={props.scopeFieldId} board={props.board}\n value={c.scope} onChange={c.setScope} counts={c.scopeCounts}\n testIdPrefix={testIdPrefix}\n />\n <TableFilter.Layout>\n <TableFilter.Main>\n <GridMain\n c={c}\n getRowId={props.getRowId}\n renderCard={props.renderCard}\n renderListRow={props.renderListRow}\n listGroup={props.listGroup}\n board={props.board}\n rowDetail={props.rowDetail}\n dataTestId={dataTestId}\n testIdPrefix={testIdPrefix}\n emptyState={body}\n />\n <DataViewsPagination c={c} testIdPrefix={testIdPrefix} />\n </TableFilter.Main>\n {inlineFilters ? null : <GridFilterPanel {...filterProps} />}\n </TableFilter.Layout>\n {useModal && <FilterDialog open={c.filterOpen} onClose={() => c.setFilterOpen(false)} {...filterProps} />}\n </Stack>\n </TableFilter>\n );\n}\n\nexport function GridShell<T extends Record<string, unknown>>(props: GridShellProps<T>): React.JSX.Element {\n const {\n c,\n fields,\n rangeFields,\n testIdPrefix,\n renderCard,\n renderListRow,\n board,\n defaultLayout,\n ignoreStoredLayout,\n inlineFilters = false,\n alwaysShowSearch = false,\n } = props;\n const filters = useGridShellFilters({\n c,\n inlineFilters,\n fields,\n rangeFields,\n testIdPrefix,\n alwaysShowSearch,\n hasExport: props.exportConfig !== undefined,\n });\n return (\n <DataViewsLayoutProvider\n canUseCards={Boolean(renderCard)}\n canUseList={Boolean(renderListRow)}\n // The board reuses the entity's card, so it needs BOTH — a `board` with no\n // `renderCard` offers no board rather than throwing.\n canUseBoard={Boolean(board && renderCard)}\n defaultLayout={defaultLayout}\n ignoreStoredLayout={ignoreStoredLayout}\n viewLayout={c.state.layout}\n >\n <LayoutStateSync c={c} />\n <ShellStack props={props} filters={filters} />\n </DataViewsLayoutProvider>\n );\n}\n"],"mappings":"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","names":["default"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/DataViews/base-list-card-slots.tsx"],"sourcesContent":["\"use client\";\n\nimport { Fragment, type ReactNode } from \"react\";\n\nimport { DescriptionItem, type DescriptionItemProps } from \"../DescriptionItem\";\nimport { RAIL_GAP_PX } from \"./list-card-rails\";\nimport { Box } from \"../../../mui/Box\";\nimport { Text } from \"../../typography/Text\";\nimport type { Theme } from \"@mui/material/styles/index.js\";\n\nimport { rem, sxRem } from \"../../../tokens/relative\";\n\n/**\n * WHAT SITS IN EACH RAIL.\n *\n * Split from `base-list-card` at the size gate: that module is the shell, the\n * rails and the states; this is the content of each column.\n */\n\n/** Below this the row drops its middle columns. */\nexport const META_BREAK = 520;\n/** …and below this it leaves the shared rails and goes two-line. */\nexport const STACK_BREAK = 360;\n\n/** Money and dates line up only if their digits are the same width. */\nconst TABULAR = { fontVariantNumeric: \"tabular-nums\" } as const;\n\nconst CLAMP = {\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n} as const;\n\n/**\n * Title over subtitle — and, when the row navigates, the anchor that covers it.\n *\n * The link is a real `<a>` stretched by `::after` over the whole card rather\n * than a click handler on a `<div>`. That buys cmd-click, middle-click, \"copy\n * link address\", the status bar preview and correct tab order, and it stops the\n * buttons elsewhere in the row from being interactive elements nested inside a\n * clickable one.\n */\nexport function ListCardCaption({\n title,\n subtitle,\n href,\n target,\n testId,\n}: {\n title?: ReactNode;\n subtitle?: ReactNode;\n href?: string;\n target?: string;\n testId?: string;\n}): React.JSX.Element {\n return (\n <Box data-slot=\"caption\" sx={{ minWidth: 0 }}>\n {title != null && (\n <Text variant=\"heading\" size=\"sm\" weight=\"bold\" as=\"p\">\n <Box\n {...(href ? { component: \"a\", href, target } : { component: \"span\" })}\n data-testid={testId}\n sx={{\n display: \"block\",\n lineHeight: 1.2,\n fontSize: sxRem(14.4),\n color: \"inherit\",\n textDecoration: \"none\",\n ...CLAMP,\n ...(href\n ? {\n \"&::after\": {\n content: '\"\"',\n position: \"absolute\",\n inset: 0,\n // Under the checkbox, drag grip, actions and menu, which\n // all raise themselves to 1.\n zIndex: 0,\n },\n \"&:hover\": { textDecoration: \"underline\" },\n }\n : {}),\n }}\n >\n {title}\n </Box>\n </Text>\n )}\n {subtitle != null && (\n <Text variant=\"caption\" size=\"xs\" color=\"secondary\" as=\"p\">\n <Box component=\"span\" sx={{ display: \"block\", ...CLAMP }}>\n {subtitle}\n </Box>\n </Text>\n )}\n </Box>\n );\n}\n\n/** One rule between two columns. Shared, so every gap gets the same mark. */\nfunction MetaRule(): React.JSX.Element {\n return (\n <Box\n aria-hidden\n sx={{\n flex: \"0 0 auto\",\n color: \"text.disabled\",\n opacity: 0.5,\n userSelect: \"none\",\n fontSize: sxRem(14),\n // A cancelled row strikes the whole meta cluster, and a struck `|` is a\n // dagger. The rule is punctuation, not data — nothing to void.\n textDecoration: \"none\",\n }}\n >\n |\n </Box>\n );\n}\n\n/**\n * The middle columns: stacked label-over-value pairs, separated by a rule.\n *\n * Stacked rather than side by side because `DATA 05/08/2026` inline spends the\n * horizontal room the value rail needs, and the separator is what stops two\n * adjacent pairs reading as one four-word phrase.\n *\n * EVEN GAPS, NOT EVEN BOXES. The rail takes a share of the row's spare width\n * per pair (see `metaRail`), and the obvious way to spend it — give every pair\n * an equal-width box and centre its content — puts the separator on the BOX\n * boundary, which is only the visual midpoint when both pairs are the same\n * width. They never are: `05/08/2026, 13:45` reaches almost to the edge of its\n * box while `PIX` stops well short of its own, so the rule ends up crowded\n * against the date and adrift from the method.\n *\n * So the pairs are sized to their content and the SPARE space is what gets\n * divided evenly. `space-evenly` gives every gap — including the two either\n * side of each separator — the same width, which puts each rule exactly halfway\n * between the two labels it separates, whatever they happen to say.\n */\nexport function ListCardMeta({\n meta,\n metaSlot,\n trailingRule,\n}: {\n meta?: DescriptionItemProps[];\n metaSlot?: ReactNode;\n /** Close the run with a rule, dividing the last pair from the value. */\n trailingRule?: boolean;\n}): React.JSX.Element {\n const items = meta ?? [];\n return (\n <Box\n data-slot=\"meta\"\n sx={(theme) => ({\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-evenly\",\n // A FLOOR, not the spacing itself: `space-evenly` supplies the rest, and\n // this is only what keeps a rail with no room to spare from running the\n // date straight into the rule.\n gap: 1,\n whiteSpace: \"nowrap\",\n ...TABULAR,\n // Rung 1 of the ladder.\n [`@container (max-width: ${rem(theme, META_BREAK)})`]: { display: \"none\" },\n })}\n >\n {items.map((item, index) => (\n <Fragment key={`${item.label}-${index}`}>\n {/* ITS OWN ITEM, not the first child of the pair that follows it.\n Nested inside, the rule travelled with that pair's centred content\n and came to rest nearer one label than the other — a separator\n visibly closer to MÉTODO than to DATA reads as belonging to it. */}\n {index > 0 && <MetaRule />}\n {/* Centred: a stacked pair sitting in its own column reads as one\n unit only when the label is over the value rather than flush left\n of a value shorter than it — `MÉTODO` above `PIX` was visibly\n unhinged from it. Overridable per item. */}\n <Box\n sx={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n minWidth: 0,\n // Sized to the pair, so the gaps either side of it are free space\n // that `space-evenly` can equalise.\n flex: \"0 0 auto\",\n }}\n >\n <DescriptionItem orientation=\"vertical\" align=\"center\" {...item} />\n </Box>\n </Fragment>\n ))}\n {metaSlot}\n {trailingRule && items.length > 0 && <MetaRule />}\n </Box>\n );\n}\n\n/**\n * The value sits flush against the meta rail, with no gap of its own.\n *\n * Its divider is now the LAST ITEM OF THE META CLUSTER, placed by the same\n * `space-evenly` that places the rules between the pairs — so it is equidistant\n * from `PIX` and from `R$ 13,90` for free, which a rule centred in the rail gap\n * could never be: the cluster's content stops well short of the rail's right\n * edge, leaving that rule 150px from the method and 12px from the money.\n *\n * Cancelling this one gap is what makes the two distances equal. Below\n * `META_BREAK` the cluster (and its rule) are gone, so the gap comes back —\n * otherwise the value would sit straight against the title.\n */\nconst valueFlush = (theme: Theme) => ({\n marginLeft: rem(theme, -RAIL_GAP_PX),\n [`@container (max-width: ${rem(theme, META_BREAK)})`]: { marginLeft: 0 },\n});\n\n/** The value, on its own rail, never truncated and never shunted by the chip. */\nfunction ListCardValue({ value }: { value: ReactNode }): React.JSX.Element {\n return (\n <Text variant=\"body\" size=\"sm\" weight=\"medium\" as=\"span\">\n <Box\n component=\"span\"\n sx={{ fontSize: sxRem(14), whiteSpace: \"nowrap\", ...TABULAR }}\n >\n {value}\n </Box>\n </Text>\n );\n}\n\n/**\n * The actions and the menu, at the end of the row.\n *\n * Actions are revealed on hover and `:focus-within` — always-visible buttons on\n * every row of fifty is a lot of chrome for something used on one of them.\n * `:focus-within` is what keeps them reachable by keyboard, and `visibility`\n * rather than `display` keeps their space reserved so nothing shifts.\n */\nexport function ListCardActions({\n actions,\n alwaysVisible,\n menu,\n testId,\n}: {\n actions?: ReactNode;\n alwaysVisible?: boolean;\n menu?: ReactNode;\n testId: (slot: string) => string | undefined;\n}): React.JSX.Element | null {\n if (actions == null && menu == null) return null;\n return (\n // z-index 1: above the stretched link, so these stay clickable.\n <Box\n data-slot=\"actions\"\n sx={{ display: \"flex\", alignItems: \"center\", gap: 0.5, position: \"relative\", zIndex: 1 }}\n >\n {actions && (\n <Box\n data-testid={testId(\"actions\")}\n onClick={(event) => event.stopPropagation()}\n sx={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 0.5,\n ...(alwaysVisible\n ? {}\n : {\n visibility: \"hidden\",\n \".MuiPaper-root:hover &, .MuiPaper-root:focus-within &\": {\n visibility: \"visible\",\n },\n }),\n }}\n >\n {actions}\n </Box>\n )}\n {menu && (\n <Box data-testid={testId(\"menu\")} onClick={(event) => event.stopPropagation()}>\n {menu}\n </Box>\n )}\n </Box>\n );\n}\n\n/** Value and actions — separate rails, not one flex run. */\nexport function ListCardTail({\n value,\n separated,\n actions,\n actionsAlwaysVisible,\n menu,\n testId,\n}: {\n value?: ReactNode;\n /** Whether a meta cluster precedes the value and wants dividing from it. */\n separated?: boolean;\n actions?: ReactNode;\n actionsAlwaysVisible?: boolean;\n menu?: ReactNode;\n testId: (slot: string) => string | undefined;\n}): React.JSX.Element {\n return (\n <>\n <Box\n data-slot=\"value\"\n sx={(theme) => ({\n textAlign: \"right\",\n ...(separated && value != null ? valueFlush(theme) : {}),\n })}\n data-testid={testId(\"value\")}\n >\n {value != null && <ListCardValue value={value} />}\n </Box>\n <ListCardActions\n actions={actions}\n alwaysVisible={actionsAlwaysVisible}\n menu={menu}\n testId={testId}\n />\n </>\n );\n}\n"],"mappings":"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","names":["Fragment","default"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/DataViews/data-views-shell-toolbar.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * The toolbar band, fed from the controller — ~25 props of pure forwarding and\n * nothing else, which is why it lives in its own file rather than in the shell.\n */\nimport { type ColumnVisibilityOption } from \"../../layout/ContentToolbar\";\n\nimport type { DisplayPanelView } from \"./data-views-display-panel\";\nimport type { DataViewExport } from \"./data-views-export\";\nimport { GridToolbar } from \"./data-views-toolbar\";\nimport type { RowAction } from \"./data-views-types\";\nimport type { DataViewsController } from \"./use-data-views-state\";\n\n/**\n * The toolbar band, fed from the controller. Split out of `GridShell` for that\n * function's size budget — it is ~25 props of pure forwarding and nothing else.\n */\nexport function ShellToolbar<T extends Record<string, unknown>>({\n c,\n rows,\n testIdPrefix,\n rowActions,\n bulkActions,\n selectionExtra,\n toolbarRightSlot,\n showInline,\n compactControls,\n counterHidden,\n sortKinds,\n displayView,\n exportConfig,\n filterControls,\n barRef,\n}: {\n c: DataViewsController<T>;\n rows: T[];\n testIdPrefix: string;\n sortKinds?: Record<string, string>;\n displayView?: DisplayPanelView;\n exportConfig?: DataViewExport;\n rowActions?: RowAction<T>[];\n bulkActions?: (selectedRows: T[], clearSelection: () => void) => React.ReactNode;\n /** Already resolved by the shell, which is the party that knows the page. */\n selectionExtra?: React.ReactNode;\n toolbarRightSlot?: React.ReactNode;\n /** Search + filters, rendered on the toolbar line (see `GridToolbar`). */\n filterControls?: React.ReactNode;\n barRef?: React.Ref<HTMLDivElement>;\n showInline: boolean;\n /** Step 2 of the ladder: Exibir/Exportar as icons only. */\n compactControls?: boolean;\n /** Step 5, last resort: drop the counter so the row still fits one line. */\n counterHidden?: boolean;\n}): React.JSX.Element {\n const columnOptions: ColumnVisibilityOption[] = c.hideableColumns.map((col) => ({\n id: col.id,\n label: col.label,\n visible: c.state.visibleColumns.includes(col.id),\n }));\n return (\n <GridToolbar\n c={c}\n sortKinds={sortKinds}\n displayView={displayView}\n exportConfig={exportConfig}\n filterControls={filterControls}\n barRef={barRef}\n compactControls={compactControls}\n counterHidden={counterHidden}\n testIdPrefix={testIdPrefix}\n selectedRows={c.selectedRows}\n selectAll={c.selectAll}\n clearSelection={c.clearSelection}\n rowActions={rowActions}\n bulkActions={bulkActions}\n selectionExtra={selectionExtra}\n sortFields={c.resolvedSortFields}\n activeSortField={c.activeSortField}\n activeSortOrder={c.activeSortOrder}\n onChangeSort={(field, order) => c.patch({ sortBy: [{ id: field, dir: order }] })}\n matchedCount={c.matched.length}\n totalCount={c.serverMode ? c.serverTotalCount : rows.length}\n toolbarRightSlot={toolbarRightSlot}\n columnOptions={columnOptions}\n onToggleColumn={c.toggleColumn}\n filterOpen={c.filterOpen}\n setFilterOpen={c.setFilterOpen}\n activeFilterCount={c.activeFilterCount}\n showFilterTrigger={!showInline}\n />\n );\n}\n\n/** Wires the controller into the shared toolbar + filter panel + grid/cards body. */\n"],"mappings":";;;;;AA6DI;AA3CG,SAAS,aAAgD;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAoBsB;AACpB,QAAM,gBAA0C,EAAE,gBAAgB,IAAI,CAAC,SAAS;AAAA,IAC9E,IAAI,IAAI;AAAA,IACR,OAAO,IAAI;AAAA,IACX,SAAS,EAAE,MAAM,eAAe,SAAS,IAAI,EAAE;AAAA,EACjD,EAAE;AACF,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc,EAAE;AAAA,MAChB,WAAW,EAAE;AAAA,MACb,gBAAgB,EAAE;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,MACA,YAAY,EAAE;AAAA,MACd,iBAAiB,EAAE;AAAA,MACnB,iBAAiB,EAAE;AAAA,MACnB,cAAc,CAAC,OAAO,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,IAAI,OAAO,KAAK,MAAM,CAAC,EAAE,CAAC;AAAA,MAC/E,cAAc,EAAE,QAAQ;AAAA,MACxB,YAAY,EAAE,aAAa,EAAE,mBAAmB,KAAK;AAAA,MACrD;AAAA,MACA;AAAA,MACA,gBAAgB,EAAE;AAAA,MAClB,YAAY,EAAE;AAAA,MACd,eAAe,EAAE;AAAA,MACjB,mBAAmB,EAAE;AAAA,MACrB,mBAAmB,CAAC;AAAA;AAAA,EACtB;AAEJ;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/DataViews/DataViewsTableBase.tsx"],"sourcesContent":["\"use client\";\n\nimport type { SortFieldDefinition } from \"../../layout/ContentToolbar\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\n\nimport { DataViewsGrid } from \"./DataViewsGrid\";\nimport type { SelectionExtraRender } from \"./data-views-selection-extra\";\nimport type { ListGroupConfig } from \"./list-card-rails\";\nimport type { DisplayPanelView } from \"./data-views-display-panel\";\nimport { viewStateKey } from \"./data-views-dirty\";\nimport { DeleteViewDialog } from \"./DeleteViewDialog\";\nimport type { BoardConfig } from \"./DataViewsBoard\";\nimport type { DataViewExport } from \"./data-views-export\";\nimport type { ScopeConfig } from \"./data-views-scopes\";\nimport type { DataViewRowDetail } from \"./data-views-row-detail\";\nimport { ViewDialogs, ViewMutationErrorAlert } from \"./data-views-table-parts\";\nimport {\n useSavedViewsController,\n type SavedViewsController,\n} from \"./use-saved-views-controller\";\nimport {\n type DataViewColumn,\n type DataViewsLayout,\n type DataViewServer,\n type DataViewState,\n type DataViewSyncState,\n type DataViewPersistence,\n type DataViewRouter,\n type FilterFieldConfig,\n type RangeFieldConfig,\n type DataViewCardSelection,\n type RowAction,\n type SavedViewSummary,\n} from \"./data-views-types\";\n\nexport interface DataViewsTableBaseProps<T extends Record<string, unknown>> {\n /** The applied-view id read from the URL (`?view=`) on load, or null. */\n initialViewId?: string | null;\n /** Injected saved-view persistence (create/update/delete). */\n persistence: DataViewPersistence;\n /** Injected router side-effects (URL sync + refresh). */\n router: DataViewRouter;\n rows: T[];\n columns: DataViewColumn<T>[];\n fields: FilterFieldConfig<T>[];\n /** Optional numeric min/max range filters (advanced \"filter by amount\"). */\n rangeFields?: RangeFieldConfig<T>[];\n getRowId: (row: T) => string | number;\n onRowClick?: (row: T) => void;\n emptyState?: React.ReactNode;\n dataTestId?: string;\n testIdPrefix?: string;\n /** The user's + shared views for this table (from the server). */\n views: SavedViewSummary[];\n /** Big page title in the table header, beside the funnel + gear (GTA layout). */\n title?: string;\n /** Primary page actions (e.g. \"Novo produto\") rendered at the header's right. */\n headerActions?: React.ReactNode;\n /** Sort options for the toolbar's \"Sort By\" dropdown (defaults to sortable columns). */\n sortFields?: SortFieldDefinition[];\n /**\n * Per-sort-field VALUE KIND (`\"currency\" | \"number\" | \"date\" | \"text\"`), so the\n * Exibir panel phrases the direction in that column's own terms. \"Crescente\"\n * on a currency column is a puzzle; \"Menor → maior\" is not. Defaults to text.\n */\n sortKinds?: Record<string, string>;\n /**\n * Opt-in \"Exportar\" control. The grid hands the host the current query,\n * UNPAGINATED, and the host re-queries — the grid never fetches, and an\n * export therefore follows the filters rather than the loaded page.\n */\n exportConfig?: DataViewExport;\n /** Notified with the currently-visible (filtered) rows, so Export matches the view. */\n onVisibleRowsChange?: (rows: T[]) => void;\n /** Reusable row actions driving both the row \"⋮\" kebab and the bulk menu. */\n rowActions?: RowAction<T>[];\n /** Leading control in the auto kebab column (e.g. a favourite star). */\n rowActionsLeading?: (row: T) => React.ReactNode;\n /** Low-level bulk-action override; prefer `rowActions`. */\n bulkActions?: (selectedRows: T[], clearSelection: () => void) => React.ReactNode;\n /** A selection-widening control beside the count (e.g. \"select all matching\"). */\n selectionExtra?: SelectionExtraRender<T>;\n /** Bespoke per-row menu (an entity's self-contained 3-dots menu) instead of the auto kebab. */\n renderRowMenu?: (row: T) => React.ReactNode;\n /** Opt-in expandable rows (table layout only) — see {@link DataViewRowDetail}. */\n rowDetail?: DataViewRowDetail<T>;\n /** Opt-in \"Grade\" (cards) layout — a card renderer per row; adds a Grade/Tabela toggle. */\n renderCard?: (row: T, selection: DataViewCardSelection) => React.ReactNode;\n /** Opt-in \"Quadro\" (board) layout — the loaded page as columns of one field. Needs `renderCard`. */\n board?: BoardConfig<T>;\n /** Opt-in \"Lista\" layout — one full-width, entity-rendered row per record (FUT-733). */\n renderListRow?: (row: T, selection: DataViewCardSelection) => React.ReactNode;\n /** The Lista's shared columns, so its rows line up by construction not convention. */\n listGroup?: ListGroupConfig<T>;\n /** The page-level partition rendered as tabs under the toolbar (server mode only). */\n scopes?: ScopeConfig[];\n /** The row field the scopes partition by — used only to reject a pill over the same field. */\n scopeFieldId?: string;\n /** Which layout to show first when the user has expressed no preference (default \"table\"). */\n defaultLayout?: DataViewsLayout;\n /**\n * Ignore the remembered cross-screen layout preference and pin to\n * `defaultLayout`. For tables that exist to SHOW a layout — stories, docs,\n * screenshots — not for real screens.\n */\n ignoreStoredLayout?: boolean;\n /** Opt into the responsive inline filter UX (collapsible row / modal). Default keeps the panel. */\n inlineFilters?: boolean;\n /** Keep the inline search visible with no filter fields and no active search. */\n alwaysShowSearch?: boolean;\n /** Server-mode wiring (FUT-180): backend-driven rows/total + re-fetch. Omit for client mode. */\n server?: DataViewServer;\n /** Seed the initial view state (search/pills/ranges/sort) from the URL when no saved view applies. */\n initialState?: DataViewState;\n}\n\n/**\n * Derive the grid's reactive `syncState` from the URL-seeded `initialState` in\n * server mode so browser back/forward RE-APPLIES the search/pills/sort controls\n * (merging over live state, preserving hidden columns — see {@link DataViewSyncState}).\n * Client-mode tables (no `server`) get `undefined`. Callers memoize `initialState`\n * on the URL, so this reference only changes on genuine navigations.\n */\nfunction useUrlSyncState(\n server: DataViewServer | undefined,\n initialState: DataViewState | undefined,\n): DataViewSyncState | undefined {\n const isServerMode = server !== undefined;\n return useMemo<DataViewSyncState | undefined>(\n () =>\n isServerMode && initialState\n ? {\n search: initialState.search,\n pills: initialState.pills,\n ranges: initialState.ranges,\n sortBy: initialState.sortBy,\n // The scope belongs in the URL-driven slice alongside them: a\n // `?view=recusados`-style deep link and browser back/forward must\n // move the tab strip, and they must do it WITHOUT resetting the\n // user's hidden columns — which is the whole reason this is a\n // merging `syncState` and not a replacing `appliedState`.\n scope: initialState.scope,\n }\n : undefined,\n [isServerMode, initialState],\n );\n}\n\n/**\n * Resolve the initial applied view: a `?view=<id>` shortcut (FUT-90) wins, else\n * the user's default view, else none. Drives the seed state + trigger label.\n */\nfunction resolveInitialView(\n views: SavedViewSummary[],\n requestedId: string | null,\n): SavedViewSummary | undefined {\n const requested = requestedId ? views.find((view) => view.id === requestedId) : undefined;\n return requested ?? views.find((view) => view.isDefault);\n}\n\n/**\n * The Exibir panel's view chrome, assembled from the saved-views controller.\n * Extracted so {@link DataViewsTableBase} stays inside its size budget.\n */\nfunction buildDisplayView({\n ctl,\n views,\n activeView,\n dirty,\n onRequestDelete,\n}: {\n ctl: SavedViewsController;\n views: SavedViewSummary[];\n activeView: SavedViewSummary | undefined;\n dirty: boolean;\n /** Opens the confirmation; the delete itself happens on confirm. */\n onRequestDelete: (view: SavedViewSummary) => void;\n}): DisplayPanelView {\n return {\n activeViewName: ctl.activeViewName,\n dirty,\n onReset: () => (activeView ? ctl.applyView(activeView) : ctl.selectMain()),\n // Only offer \"Atualizar\" when there IS a view to update — otherwise the\n // single footer button is a plain \"Salvar visão\".\n onUpdate: activeView ? () => ctl.openEdit(activeView) : undefined,\n onSaveAs: ctl.openCreate,\n // The views themselves, not a dropdown: the panel renders them in its own\n // body (see `data-views-view-nav`), so there is no second popover to clip\n // the row actions.\n nav: {\n views,\n activeViewId: activeView?.id ?? null,\n onSelectView: (id) => {\n const next = id === null ? null : views.find((view) => view.id === id);\n if (next) ctl.applyView(next);\n else ctl.selectMain();\n },\n onEditView: ctl.openEdit,\n onPatchView: (view, changes) => void ctl.patchView(view, changes),\n onDeleteView: onRequestDelete,\n },\n };\n}\n\n/**\n * \"Are there unsaved changes?\" — the dot on Exibir, and whether Redefinir and\n * Salvar visão are live.\n *\n * Two things it gets right that the inline version did not. It compares\n * NORMALISED states (`viewStateKey`), so a filter applied and then removed is\n * clean again rather than clean-looking but flagged; and it re-baselines after\n * a SAVE, because the state just written is the clean one from that point.\n *\n * The baseline is the first state the grid emits for a view, not the view\n * itself: the grid normalises what it is handed — resolving visible columns,\n * filling in layout — so the applied view is never byte-identical to the state\n * it produces.\n */\nfunction useDirtyTracking(ctl: SavedViewsController): {\n dirty: boolean;\n noteState: (state: DataViewState) => void;\n markSaved: () => void;\n} {\n const [dirty, setDirty] = useState(false);\n const [savedAt, setSavedAt] = useState(0);\n const baseline = useRef<string | null>(null);\n const appliedKey = JSON.stringify(ctl.applied ?? null);\n\n useEffect(() => {\n baseline.current = null;\n setDirty(false);\n }, [appliedKey, savedAt]);\n\n return {\n dirty,\n noteState: (state) => {\n ctl.currentRef.current = state;\n const key = viewStateKey(state);\n if (baseline.current === null) {\n baseline.current = key;\n setDirty(false);\n return;\n }\n const next = key !== baseline.current;\n setDirty((prev) => (prev === next ? prev : next));\n },\n markSaved: () => setSavedAt((tick) => tick + 1),\n };\n}\n\n/**\n * The reusable admin table (FUT-89): the DataViews grid plus the full saved-views\n * experience — a views dropdown, a save/edit modal (with preview), and a manage\n * dialog. Framework-agnostic: saved-view persistence and router side-effects are\n * INJECTED (`persistence`, `router`, `initialViewId`) so the host app wires them\n * to its backend + framework router. A default view auto-applies on load; applying\n * a view restores its filters + columns + sort. Each table supplies its own columns\n * + filter fields; everything else is shared.\n */\nexport function DataViewsTableBase<T extends Record<string, unknown>>(\n props: DataViewsTableBaseProps<T>,\n): React.JSX.Element {\n // Forwarded as a whole rather than restated name-by-name twice (as in\n // DataViewsGrid): this component only ADDS the saved-views chrome, and a\n // 30-name destructure repeated in the JSX is exactly where a newly added prop\n // silently stops being passed on.\n const {\n initialViewId = null,\n persistence,\n router,\n columns,\n fields,\n testIdPrefix = \"table\",\n views,\n server,\n initialState,\n } = props;\n const initialView = resolveInitialView(views, initialViewId);\n const columnIds = columns.map((col) => col.id);\n const ctl = useSavedViewsController(persistence, router, columnIds, views, initialView, initialState);\n // Unsaved-changes flag for the Exibir panel. Set from `onStateChange` rather\n // than derived in render because the live state lives in a REF (the grid owns\n // it); the equality bail-out in `setDirty` is what stops the update loop.\n const { dirty, noteState, markSaved } = useDirtyTracking(ctl);\n // Deleting a saved view is confirmed, not immediate — see `DeleteViewDialog`.\n const [pendingDelete, setPendingDelete] = useState<SavedViewSummary | null>(null);\n // The view the panel's \"Redefinir\" restores: the applied one, or the built-in\n // \"Visão principal\" when none is.\n const activeView = views.find((view) => view.name === ctl.activeViewName);\n const displayView = buildDisplayView({\n ctl,\n views,\n activeView,\n dirty,\n onRequestDelete: setPendingDelete,\n });\n // Server-mode lists re-apply URL-derived controls on back/forward (not just the mount seed).\n const syncState = useUrlSyncState(server, initialState);\n\n return (\n <>\n <ViewMutationErrorAlert error={ctl.mutationError} onClose={ctl.clearMutationError} testIdPrefix={testIdPrefix} />\n <DataViewsGrid<T>\n {...props}\n testIdPrefix={testIdPrefix}\n appliedState={ctl.applied}\n syncState={syncState}\n onStateChange={noteState}\n // The saved-views menu is NOT a toolbar control any more: it lives in\n // the Exibir panel's VISÃO header, passed through `displayView`.\n displayView={displayView}\n />\n {renderViewDialogs(ctl, fields, columns, views, testIdPrefix, markSaved)}\n <DeleteViewDialog\n view={pendingDelete}\n onClose={() => setPendingDelete(null)}\n onConfirm={(view) => {\n void ctl.handleDelete(view);\n setPendingDelete(null);\n }}\n testIdPrefix={testIdPrefix}\n />\n </>\n );\n}\n\n/** The save + manage saved-view dialogs, split out to keep the base thin. */\nfunction renderViewDialogs<T extends Record<string, unknown>>(\n ctl: SavedViewsController,\n fields: DataViewsTableBaseProps<T>[\"fields\"],\n columns: DataViewsTableBaseProps<T>[\"columns\"],\n views: SavedViewSummary[],\n testIdPrefix: string,\n onSaved: () => void,\n): React.JSX.Element {\n return (\n <ViewDialogs<T>\n saveOpen={ctl.saveOpen}\n onCloseSave={ctl.closeSave}\n currentState={ctl.editing ? ctl.editing.state : ctl.currentRef.current}\n fields={fields}\n columns={columns}\n editing={ctl.editing}\n onSave={async (payload) => {\n await ctl.handleSave(payload);\n // The saved state is the clean one from here on.\n onSaved();\n }}\n manageOpen={ctl.manageOpen}\n onCloseManage={() => ctl.setManageOpen(false)}\n views={views}\n onEditFromManage={ctl.editFromManage}\n onDelete={(view) => void ctl.handleDelete(view)}\n testIdPrefix={testIdPrefix}\n />\n );\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/Chart/chart-context.ts"],"sourcesContent":["import type { Theme } from '@mui/material/styles/index.js';\nimport type { CSSProperties } from 'react';\n\nimport type { ChartDataPoint, ChartProps, ChartSeries } from './Chart.types';\nimport { resolveAxisConfig, resolveBarGeometry, type BarGeometry, type CartesianAxisConfig } from './chart-axis';\nimport {\n getAxisStyles,\n getDefaultColors,\n getSizeStyles,\n resolveSeries,\n type SizeStyles,\n} from './chart-internals';\nimport { remPx } from '../../../tokens/relative';\n\n/**\n * Everything the per-type renderers in `chart-renderers.tsx` read, resolved\n * once from props + theme. Kept out of that file so each renderer is a small\n * JSX function over already-decided values — palette, series, axis geometry,\n * bar geometry — rather than a place where those decisions get made again\n * slightly differently.\n */\nexport interface ChartRenderContext {\n props: ChartProps;\n theme: Theme;\n sizeStyles: SizeStyles;\n chartColors: string[];\n chartSeries: ChartSeries[];\n strokeType: 'monotone' | 'linear';\n axisStyle: CSSProperties;\n gridStroke: string;\n /** Multiplier on `gridStroke`'s alpha — see `getAxisStyles`. */\n gridOpacity: number;\n axisConfig: CartesianAxisConfig;\n barGeometry: BarGeometry;\n animationDuration: number;\n commonProps: {\n data: ChartDataPoint[];\n margin: { top?: number; right?: number; bottom?: number; left?: number };\n onClick: (payload: unknown) => void;\n };\n}\n\nexport function buildChartContext(props: ChartProps, theme: Theme): ChartRenderContext {\n const sizeStyles = getSizeStyles(theme, props.size, props.height);\n const chartColors = getDefaultColors(theme, props.variant ?? 'default', props.colors);\n const { axisStyle, gridStroke, gridOpacity } = getAxisStyles(\n theme,\n props.variant ?? 'default',\n sizeStyles.fontSize,\n );\n const handleChartClick = (payload: unknown): void => {\n const chartData = payload as { activePayload?: Array<{ payload: ChartDataPoint }> };\n if (props.onClick && chartData?.activePayload?.[0]) {\n props.onClick(chartData.activePayload[0].payload);\n }\n };\n return {\n props,\n theme,\n sizeStyles,\n chartColors,\n chartSeries: resolveSeries(props.data, props.series, props.xAxisKey ?? 'name', chartColors),\n strokeType: (props.curved ?? true) ? 'monotone' : 'linear',\n axisStyle: { ...axisStyle, fontSize: sizeStyles.fontSize },\n gridStroke,\n gridOpacity,\n axisConfig: resolveAxisConfig(props, sizeStyles.tickMargin),\n barGeometry: resolveBarGeometry(props, theme),\n animationDuration: (props.animate ?? true) ? (props.animationDuration ?? 1500) : 0,\n commonProps: {\n data: props.data,\n margin: {\n top: remPx(theme, 20),\n right: remPx(theme, 30),\n left: remPx(theme, 20),\n bottom: remPx(theme, 20),\n ...marginPx(theme, props.margin),\n },\n onClick: handleChartClick,\n },\n };\n}\n\n/** A caller's margin is in design px (the prop's contract); Recharts takes px numbers. */\nfunction marginPx(theme: Theme, margin: ChartProps['margin']): ChartProps['margin'] {\n if (!margin) return undefined;\n return Object.fromEntries(\n Object.entries(margin).map(([side, px]) => [side, typeof px === 'number' ? remPx(theme, px) : px]),\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;AA0CO,SAAS,kBAAkB,OAAmB,OAAkC;AACrF,QAAM,aAAa,cAAc,OAAO,MAAM,MAAM,MAAM,MAAM;AAChE,QAAM,cAAc,iBAAiB,OAAO,MAAM,WAAW,WAAW,MAAM,MAAM;AACpF,QAAM,EAAE,WAAW,YAAY,YAAY,IAAI;AAAA,IAC7C;AAAA,IACA,MAAM,WAAW;AAAA,IACjB,WAAW;AAAA,EACb;AACA,QAAM,mBAAmB,CAAC,YAA2B;AACnD,UAAM,YAAY;AAClB,QAAI,MAAM,WAAW,WAAW,gBAAgB,CAAC,GAAG;AAClD,YAAM,QAAQ,UAAU,cAAc,CAAC,EAAE,OAAO;AAAA,IAClD;AAAA,EACF;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa,cAAc,MAAM,MAAM,MAAM,QAAQ,MAAM,YAAY,QAAQ,WAAW;AAAA,IAC1F,YAAa,MAAM,UAAU,OAAQ,aAAa;AAAA,IAClD,WAAW,EAAE,GAAG,WAAW,UAAU,WAAW,SAAS;AAAA,IACzD;AAAA,IACA;AAAA,IACA,YAAY,kBAAkB,OAAO,WAAW,UAAU;AAAA,IAC1D,aAAa,mBAAmB,OAAO,KAAK;AAAA,IAC5C,mBAAoB,MAAM,WAAW,OAAS,MAAM,qBAAqB,OAAQ;AAAA,IACjF,aAAa;AAAA,MACX,MAAM,MAAM;AAAA,MACZ,QAAQ;AAAA,QACN,KAAK,MAAM,OAAO,EAAE;AAAA,QACpB,OAAO,MAAM,OAAO,EAAE;AAAA,QACtB,MAAM,MAAM,OAAO,EAAE;AAAA,QACrB,QAAQ,MAAM,OAAO,EAAE;AAAA,QACvB,GAAG,SAAS,OAAO,MAAM,MAAM;AAAA,MACjC;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;AAGA,SAAS,SAAS,OAAc,QAAoD;AAClF,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,OAAO;AAAA,IACZ,OAAO,QAAQ,MAAM,EAAE,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,OAAO,OAAO,WAAW,MAAM,OAAO,EAAE,IAAI,EAAE,CAAC;AAAA,EACnG;AACF;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/DataViews/base-list-card-geometry.tsx"],"sourcesContent":["\"use client\";\n\nimport { useTheme, type Theme } from \"@mui/material/styles/index.js\";\n\nimport {\n CARD_RADIUS,\n cardSurfaceStyles,\n isActionable,\n isSelectable,\n slotTestIds,\n} from \"./card-surface\";\nimport { useDragItem } from \"./data-views-drag\";\nimport { DENSITY_ROW_PADDING } from \"./data-views-layout-context\";\nimport { RAIL_COUNT, RAIL_GAP, railsTemplateFor, useListRails } from \"./list-card-rails\";\nimport { STACK_BREAK } from \"./base-list-card-slots\";\nimport type { BaseListCardProps } from \"./base-list-card\";\nimport { rem } from \"../../../tokens/relative\";\n\n/**\n * THE ROW'S GEOMETRY AND SURFACE, split from the component at the size gate.\n *\n * Everything here answers \"what shape is this row, and where do its slots land\"\n * — the rails, the density padding, the two-line collapse, the drag and\n * selection plumbing. None of it renders anything, which is why the two halves\n * can live apart without either becoming harder to follow.\n */\n/**\n * Whether a click was really a click, or the tail of a text selection.\n *\n * Without this, selecting an order id to copy it navigates away instead — the\n * single most annoying thing a clickable row does.\n */\nfunction isTextSelection(): boolean {\n return (globalThis.getSelection?.()?.toString().length ?? 0) > 0;\n}\n\n/** Keyboard equivalence for a card that acts but does not navigate. */\nfunction clickKeys(onClick: () => void) {\n return (event: React.KeyboardEvent): void => {\n if (event.key !== \"Enter\" && event.key !== \" \") return;\n event.preventDefault();\n onClick();\n };\n}\n\n/**\n * Geometry: the rails, the density padding, the two-line collapse.\n *\n * SCALE IS `zoom`, NOT A SET OF MULTIPLIED FONT SIZES.\n *\n * It used to be the latter, on exactly three values — title, value, row padding\n * — so the slider left the subtitle, the meta labels, the rules, the checkbox,\n * the grip, the chip and the menu at their fixed sizes, and the row came apart\n * as you dragged it. Multiplying the rest is not a fix: the checkbox and the\n * chip are MUI internals sized in their own px, and no prop we pass reaches\n * them.\n *\n * `zoom` scales the used value of every length in the subtree — ours and theirs\n * — and unlike `transform: scale` it REFLOWS, so the row still occupies the\n * space it draws and the rails still resolve. Verified against the group: at\n * 1.4 all four rows keep identical rail edges, because subgrid tracks and the\n * zoom that reads them are the same for every row.\n */\n/** What {@link rowSx} needs to know about the row it lays out. */\ninterface RowSxOptions {\n inGroup: boolean;\n railCount: number;\n cellTemplate: string | null;\n gutters: { disclose: boolean; drag: boolean; select: boolean };\n metaColumns: number;\n pad: number;\n padY: number;\n scale: number;\n divider: boolean;\n interactive: boolean;\n draggable: boolean;\n}\n\n/**\n * DIVIDER COMPOSES WITH THE VARIANT — it changes the row's SHAPE, not its\n * surface.\n *\n * It used to set `border: 0` and hard-code its own rule colour, which discarded\n * whatever the variant had drawn: `outline`, `text` and `ghost` all collapsed\n * to one identical flush row, and the variant control silently stopped meaning\n * anything the moment `divider` was on.\n *\n * Now only the GEOMETRY changes here — the box's sides go, one edge stays — and\n * no `borderColor` is written, so the colour set by `cardSurfaceStyles` survives.\n * A variant that draws no border of its own gets the neutral rule from\n * {@link rowStyles}.\n */\nexport const rowSx = (theme: Theme, opts: RowSxOptions): Record<string, unknown> => {\n const { inGroup, railCount, cellTemplate, gutters, metaColumns, pad, padY, scale, divider, interactive, draggable } = opts;\n return {\n position: \"relative\",\n borderRadius: CARD_RADIUS,\n display: \"grid\",\n zoom: scale,\n // SUBGRID AND `container-type` CANNOT COEXIST on one element: containment\n // makes the box size independently of its parent, so the browser drops the\n // subgrid and every slot stacks into one column. (Observed exactly that —\n // computed `grid-template-columns: 1222px` on a card asking for subgrid.)\n //\n // So inside a group the GROUP is the query container and the row is the\n // subgrid; standalone, the row is both the container and its own grid.\n ...(inGroup\n ? { gridColumn: `span ${railCount}`, gridTemplateColumns: \"subgrid\" }\n : {\n containerType: \"inline-size\",\n gridTemplateColumns: cellTemplate ?? railsTemplateFor(gutters, metaColumns),\n }),\n alignItems: \"center\",\n // Wide enough that the meta cluster, the value and the status read as three\n // columns rather than one run of text — the complaint that started all this\n // was `MÉTODO PIX R$ 13,90` scanning as a single phrase.\n columnGap: RAIL_GAP,\n width: \"100%\",\n px: pad,\n py: padY,\n cursor: draggable ? \"grab\" : interactive ? \"pointer\" : undefined,\n ...(draggable ? { touchAction: \"none\", \"&:active\": { cursor: \"grabbing\" } } : {}),\n ...(interactive ? { \"&:hover\": { backgroundColor: \"action.hover\" } } : {}),\n // A real focus ring, which a clickable <div> never had.\n \"&:focus-visible\": {\n outline: `${rem(theme, 2)} solid`,\n outlineStyle: \"solid\",\n outlineColor: \"primary.main\",\n outlineOffset: rem(theme, 2),\n },\n // TWO-LINE, below the point where the shared rails stop helping.\n //\n // The standard mobile transaction row: what the record IS and what it COST\n // on the first line, the supporting detail on the second. Better than\n // truncating four columns into ellipses, and the reason each slot carries a\n // `data-slot` — the placement is explicit rather than whatever order the\n // children happen to be in.\n //\n // [ select ][ leading ][ title …………… ][ menu ]\n // [ (cells) …………… ][ value ]\n //\n // The MENU stays in the top-right corner at every width. It is the row's\n // one fixed landmark — an overflow that moves to the second line on a phone\n // is an overflow nobody finds twice.\n [`@container (max-width: ${rem(theme, STACK_BREAK)})`]: {\n gridTemplateColumns: \"auto auto minmax(0, 1fr) max-content\",\n ...(inGroup ? { gridColumn: `span ${RAIL_COUNT}` } : {}),\n rowGap: 0.75,\n columnGap: 1,\n '& > [data-slot=\"drag\"]': { display: \"none\" },\n '& > [data-slot=\"select\"]': { gridArea: \"1 / 1\" },\n '& > [data-slot=\"leading\"]': { gridArea: \"1 / 2\" },\n '& > [data-slot=\"caption\"]': { gridArea: \"1 / 3\" },\n '& > [data-slot=\"actions\"]': { gridArea: \"1 / 4\", justifyContent: \"flex-end\" },\n '& > [data-slot=\"meta\"]': { display: \"none\" },\n // Second line, starting under the title rather than under the checkbox.\n '& > [data-slot=\"value\"]': { gridArea: \"2 / 4\", textAlign: \"right\" },\n },\n ...(divider\n ? { borderRadius: 0, borderWidth: 0, borderBottomWidth: 1, borderStyle: \"solid\" }\n : {}),\n };\n};\n\n/**\n * A selectable full-width row: a marker, a title over a subtitle, labelled\n * middle columns, a value, a status, actions and a menu.\n *\n * A SHELL, like {@link BaseCard}. Domain rows live in the app and compose it.\n */\n/**\n * The id this row drags under, or nothing.\n *\n * `undefined` is the inert answer: `useDragItem` treats a missing id as \"no\n * drag\", which is how the card's own veto (`draggable={false}`) and an\n * unactionable record both switch dragging off without the card knowing\n * anything about the container above it.\n */\nfunction dragIdFor(\n props: BaseListCardProps,\n actionable: boolean,\n): string | number | undefined {\n return props.draggable === false || !actionable ? undefined : props.dragId;\n}\n\n/**\n * What the meta cluster amounts to — asked once, used three times: to size the\n * rail, to close the cluster with a rule, and to decide whether the value has\n * anything to be divided FROM.\n */\nexport function metaShape(props: BaseListCardProps): { columns: number; present: boolean } {\n const columns = props.meta?.length ?? 0;\n return { columns, present: columns > 0 || props.metaSlot != null };\n}\n\n/**\n * Everything the row derives before it can render — extracted so the component\n * stays inside the size budget.\n */\nexport function useRowShell(props: BaseListCardProps) {\n const actionable = isActionable(props.state);\n const group = useListRails();\n const scale = props.scale ?? 1;\n return {\n group,\n actionable,\n scale,\n theme: useTheme(),\n selectable: isSelectable(props),\n slot: slotTestIds(props.testId),\n drag: useDragItem(dragIdFor(props, actionable)),\n // Standalone holds no gutter open: there is no list beside it to line up\n // with, so a reserved-but-empty rail is pure inset.\n reserve: group?.reserveGutters ?? false,\n // 1, not 1.5. The row's contents still have to line up with the toolbar\n // above them, but 12px of card padding stacked on the checkbox's own 9px\n // and an empty drag gutter's 24px read as a row indented for no reason.\n //\n // Not multiplied by `scale` — the row's `zoom` already scales it, and doing\n // both would square the factor on padding alone.\n pad: 1,\n padY: DENSITY_ROW_PADDING[group?.density ?? props.density ?? \"cozy\"],\n // A card that navigates does so with a real anchor, so it takes no click\n // handler of its own — the stretched link IS the target.\n acts: props.onClick != null && props.href == null && actionable,\n };\n}\n\n/** The click/keyboard props a row that acts (but does not navigate) needs. */\nexport function actionProps(onClick: (() => void) | undefined) {\n return {\n role: \"button\",\n tabIndex: 0,\n onClick: () => {\n if (isTextSelection()) return;\n onClick?.();\n },\n onKeyDown: clickKeys(() => onClick?.()),\n };\n}\n\n/** The surface and the geometry, merged — the row's whole `sx` in one place. */\n\n/**\n * The row's painted surface, plus the divider's colour fallback.\n *\n * A variant with no border of its own (`text`, `ghost`) would draw its rule in\n * the inherited colour — the TEXT colour, i.e. a black bar across the row. The\n * neutral divider token is supplied only in that case; a variant that has a\n * border keeps it, which is the whole point of composing the two.\n */\nfunction rowSurface(\n props: BaseListCardProps,\n shell: ReturnType<typeof useRowShell>,\n): Record<string, unknown> {\n const { theme, selectable, drag } = shell;\n const surface = cardSurfaceStyles(\n { ...props, selectable, shape: \"row\", state: drag.dragging ? \"disabled\" : props.state },\n theme,\n );\n if (props.divider !== true || surface.borderColor != null) return surface;\n return { ...surface, borderBottomColor: theme.palette.divider };\n}\n\nexport function rowStyles(\n props: BaseListCardProps,\n shell: ReturnType<typeof useRowShell>,\n cellTemplate: string | null,\n): Record<string, unknown> {\n const { theme, group, selectable, drag, reserve, pad, padY, scale, acts } = shell;\n return {\n ...rowSurface(props, shell),\n ...rowSx(theme, {\n inGroup: group !== null,\n railCount: group?.railCount ?? RAIL_COUNT,\n cellTemplate,\n gutters: {\n disclose: reserve || props.children != null,\n drag: reserve || drag.draggable,\n select: reserve || selectable,\n },\n metaColumns: metaShape(props).columns,\n pad,\n padY,\n scale,\n divider: props.divider ?? false,\n interactive: acts || props.href != null,\n draggable: drag.draggable && drag.handleProps === undefined,\n }),\n };\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/DataViews/data-views-toolbar.tsx"],"sourcesContent":["\"use client\";\n\nimport Divider from \"@mui/material/Divider/index.js\";\n\nimport {\n ContentToolbar,\n FilterTrigger,\n type ColumnVisibilityOption,\n type SortFieldDefinition,\n} from \"../../layout/ContentToolbar\";\nimport { Box } from \"../../../mui/Box\";\nimport { Text } from \"../../typography/Text\";\n\nimport { useDataViewsCopy } from \"./data-views-copy-context\";\nimport { DataViewsDisplayPanel, type DisplayPanelView } from \"./data-views-display-panel\";\nimport { DataViewsExportMenu, type DataViewExport } from \"./data-views-export\";\nimport { renderBulkActions } from \"./data-views-grid-helpers\";\nimport type { RowAction } from \"./data-views-types\";\nimport type { DataViewsController } from \"./use-data-views-state\";\nimport { sxRem } from \"../../../tokens/relative\";\n\nexport interface GridToolbarProps<T extends Record<string, unknown>> {\n testIdPrefix: string;\n selectedRows: T[];\n selectAll: () => void;\n clearSelection: () => void;\n rowActions?: RowAction<T>[];\n bulkActions?: (selectedRows: T[], clearSelection: () => void) => React.ReactNode;\n /** A control between the count and the actions menu — see `selectionExtra`. */\n selectionExtra?: React.ReactNode;\n sortFields: SortFieldDefinition[];\n activeSortField: string;\n activeSortOrder: \"asc\" | \"desc\";\n onChangeSort: (field: string, order: \"asc\" | \"desc\") => void;\n matchedCount: number;\n totalCount: number;\n toolbarRightSlot?: React.ReactNode;\n columnOptions: ColumnVisibilityOption[];\n onToggleColumn: (id: string, visible: boolean) => void;\n filterOpen: boolean;\n setFilterOpen: (open: boolean) => void;\n activeFilterCount: number;\n /** Hide the \"Filtros\" slide-in trigger (compact layout shows filters inline). */\n showFilterTrigger?: boolean;\n /**\n * Search + filter controls, rendered ON the toolbar line rather than on a row\n * beneath it. Absent ⇒ the toolbar keeps its plain two-cluster shape.\n */\n filterControls?: React.ReactNode;\n /** Measures the toolbar ROW for the filter overflow — see `useFilterOverflow`. */\n barRef?: React.Ref<HTMLDivElement>;\n /** The controller, so \"Exibir\" can drive sort, columns, order and format. */\n c: DataViewsController<T>;\n /** Per-sort-field value kind, so directions read in the column's own terms. */\n sortKinds?: Record<string, string>;\n /** The saved-view chrome bracketing the Exibir panel, when the host has views. */\n displayView?: DisplayPanelView;\n /** Injected export. Absent ⇒ no Exportar control. */\n exportConfig?: DataViewExport;\n /**\n * Step 2 of the degradation ladder: Exibir/Exportar as icons only.\n * MEASURED upstream (see `useFilterOverflow`) rather than switched at a\n * breakpoint, so a two-filter page keeps its labels where a five-filter one\n * has already given them up.\n */\n compactControls?: boolean;\n /**\n * Step 5 of the ladder, and its floor: on a screen too narrow for even the\n * fully-collapsed row, the counter is dropped so the controls still fit one\n * line instead of spilling outside the toolbar.\n */\n counterHidden?: boolean;\n}\n\n/** The right-aligned toolbar controls: Sort By, the counter, zoom/layout/columns, filters. */\nfunction ToolbarRightControls<T extends Record<string, unknown>>(props: GridToolbarProps<T>): React.JSX.Element {\n const { testIdPrefix, matchedCount, totalCount, filterOpen, setFilterOpen } = props;\n return (\n <>\n {/* MEASURED, never breakpointed: `RESERVED.counter` prices it into the\n ladder, so hiding it at `md` was the ladder and a breakpoint\n disagreeing about the same pixels — which broke the row at exactly\n 900px. It is dropped only as the ladder's last rung. */}\n {!props.counterHidden && (\n <>\n <Text variant=\"caption\" as=\"span\">\n <Box\n component=\"span\"\n data-testid={`${testIdPrefix}-counter`}\n sx={{ whiteSpace: \"nowrap\" }}\n >\n {matchedCount} de {totalCount}\n </Box>\n </Text>\n {/* Divides the READING of the list from the controls that change it —\n the counter states what is on screen, everything right of here\n acts on it. */}\n <Divider\n orientation=\"vertical\"\n flexItem\n sx={{ height: sxRem(20), alignSelf: \"center\", mx: 0.5 }}\n />\n </>\n )}\n {props.toolbarRightSlot}\n {/* Sort + columns + format, in ONE control — see DataViewsDisplayPanel. */}\n <DataViewsDisplayPanel\n c={props.c}\n testIdPrefix={testIdPrefix}\n sortKinds={props.sortKinds}\n view={props.displayView}\n compact={props.compactControls}\n />\n {props.exportConfig && (\n <DataViewsExportMenu\n config={props.exportConfig}\n query={props.c.currentQuery}\n totalCount={props.totalCount}\n selectedIds={[...props.c.selectedIds]}\n columns={props.columnOptions.filter((col) => col.visible).map((col) => ({ id: col.id, label: col.label }))}\n testIdPrefix={testIdPrefix}\n compact={props.compactControls}\n />\n )}\n {props.showFilterTrigger !== false && (\n <FilterTrigger\n open={filterOpen}\n onOpenChange={setFilterOpen}\n activeCount={props.activeFilterCount}\n data-testid={`${testIdPrefix}-filters-toggle`}\n />\n )}\n </>\n );\n}\n\n/**\n * The bordered toolbar band: selection chrome + Sort By, the result counter, the\n * saved-views slot, and the filter funnel. The negative margin lets the top/bottom\n * separators reach the sidebar's vertical line and the window edge.\n */\nexport function GridToolbar<T extends Record<string, unknown>>(props: GridToolbarProps<T>): React.JSX.Element {\n const copy = useDataViewsCopy();\n const { testIdPrefix, selectedRows } = props;\n return (\n <Box\n ref={props.barRef}\n sx={{\n borderTop: 1,\n borderBottom: 1,\n borderColor: \"divider\",\n py: 1.25,\n mx: { xs: -2, md: -3 },\n px: { xs: 2, md: 3 },\n }}\n >\n <ContentToolbar\n selectAllLabel={copy.selection.selectAll}\n selectAllText={copy.selection.selectAllOnPage}\n clearAllText={copy.filters.clearAll}\n hasSelection={selectedRows.length > 0}\n selectedCount={selectedRows.length}\n selectAll={props.selectAll}\n clearSelection={props.clearSelection}\n selectAllTestId={`${testIdPrefix}-select-all`}\n clearAllTestId={`${testIdPrefix}-clear-all`}\n selectionExtra={props.selectionExtra}\n actions={renderBulkActions({\n rowActions: props.rowActions,\n bulkActions: props.bulkActions,\n selectedRows,\n clearSelection: props.clearSelection,\n testIdPrefix,\n })}\n leadingControls={props.filterControls}\n // Selection takes the whole line: no Select All while browsing, and no\n // search/filters/Exibir/Exportar once a row is ticked.\n exclusiveSelection\n rightControls={<ToolbarRightControls {...props} />}\n />\n </Box>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,OAAO,aAAa;AAkFZ,mBACE,KACE,YAFJ;AATR,SAAS,qBAAwD,OAA+C;AAC9G,QAAM,EAAE,cAAc,cAAc,YAAY,YAAY,cAAc,IAAI;AAC9E,SACE,iCAKG;AAAA,KAAC,MAAM,iBACN,iCACE;AAAA,0BAAC,QAAK,SAAQ,WAAU,IAAG,QACzB;AAAA,QAACA;AAAA,QAAA;AAAA,UACC,WAAU;AAAA,UACV,eAAa,GAAG,YAAY;AAAA,UAC5B,IAAI,EAAE,YAAY,SAAS;AAAA,UAE1B;AAAA;AAAA,YAAa;AAAA,YAAK;AAAA;AAAA;AAAA,MACrB,GACF;AAAA,MAIA;AAAA,QAAC;AAAA;AAAA,UACC,aAAY;AAAA,UACZ,UAAQ;AAAA,UACR,IAAI,EAAE,QAAQ,MAAM,EAAE,GAAG,WAAW,UAAU,IAAI,IAAI;AAAA;AAAA,MACxD;AAAA,OACF;AAAA,IAED,MAAM;AAAA,IAEP;AAAA,MAAC;AAAA;AAAA,QACC,GAAG,MAAM;AAAA,QACT;AAAA,QACA,WAAW,MAAM;AAAA,QACjB,MAAM,MAAM;AAAA,QACZ,SAAS,MAAM;AAAA;AAAA,IACjB;AAAA,IACC,MAAM,gBACL;AAAA,MAAC;AAAA;AAAA,QACC,QAAQ,MAAM;AAAA,QACd,OAAO,MAAM,EAAE;AAAA,QACf,YAAY,MAAM;AAAA,QAClB,aAAa,CAAC,GAAG,MAAM,EAAE,WAAW;AAAA,QACpC,SAAS,MAAM,cAAc,OAAO,CAAC,QAAQ,IAAI,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,IAAI,IAAI,OAAO,IAAI,MAAM,EAAE;AAAA,QACzG;AAAA,QACA,SAAS,MAAM;AAAA;AAAA,IACjB;AAAA,IAED,MAAM,sBAAsB,SAC3B;AAAA,MAAC;AAAA;AAAA,QACC,MAAM;AAAA,QACN,cAAc;AAAA,QACd,aAAa,MAAM;AAAA,QACnB,eAAa,GAAG,YAAY;AAAA;AAAA,IAC9B;AAAA,KAEJ;AAEJ;AAOO,SAAS,YAA+C,OAA+C;AAC5G,QAAM,OAAO,iBAAiB;AAC9B,QAAM,EAAE,cAAc,aAAa,IAAI;AACvC,SACE;AAAA,IAACA;AAAA,IAAA;AAAA,MACC,KAAK,MAAM;AAAA,MACX,IAAI;AAAA,QACF,WAAW;AAAA,QACX,cAAc;AAAA,QACd,aAAa;AAAA,QACb,IAAI;AAAA,QACJ,IAAI,EAAE,IAAI,IAAI,IAAI,GAAG;AAAA,QACrB,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE;AAAA,MACrB;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACC,gBAAgB,KAAK,UAAU;AAAA,UAC/B,eAAe,KAAK,UAAU;AAAA,UAC9B,cAAc,KAAK,QAAQ;AAAA,UAC3B,cAAc,aAAa,SAAS;AAAA,UACpC,eAAe,aAAa;AAAA,UAC5B,WAAW,MAAM;AAAA,UACjB,gBAAgB,MAAM;AAAA,UACtB,iBAAiB,GAAG,YAAY;AAAA,UAChC,gBAAgB,GAAG,YAAY;AAAA,UAC/B,gBAAgB,MAAM;AAAA,UACtB,SAAS,kBAAkB;AAAA,YACzB,YAAY,MAAM;AAAA,YAClB,aAAa,MAAM;AAAA,YACnB;AAAA,YACA,gBAAgB,MAAM;AAAA,YACtB;AAAA,UACF,CAAC;AAAA,UACD,iBAAiB,MAAM;AAAA,UAGvB,oBAAkB;AAAA,UAClB,eAAe,oBAAC,wBAAsB,GAAG,OAAO;AAAA;AAAA,MAClD;AAAA;AAAA,EACF;AAEJ;","names":["default"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/DataViews/base-list-card.tsx"],"sourcesContent":["\"use client\";\n\nimport Collapse from \"@mui/material/Collapse/index.js\";\nimport { type ReactNode } from \"react\";\n\nimport { Card } from \"../../layout/Card\";\nimport type { DescriptionItemProps } from \"../DescriptionItem\";\nimport { Box } from \"../../../mui/Box\";\n\nimport { type CardSurfaceProps } from \"./card-surface\";\nimport { DropIndicator } from \"./data-views-drag\";\nimport { useDisclosure } from \"./base-list-card-disclosure\";\nimport { actionProps, metaShape, rowStyles, useRowShell } from \"./base-list-card-geometry\";\nimport { DiscloseSlot, DragSlot, SelectSlot } from \"./base-list-card-gutters\";\nimport { type DataViewsDensity } from \"./data-views-layout-context\";\nimport { cellRailsTemplate } from \"./list-card-rails\";\nimport { ListCardCells, cellTracks, useCellConfig, type ListCardCellConfig } from \"./list-card-cells\";\nimport {\n ListCardActions,\n ListCardCaption,\n ListCardMeta,\n ListCardTail,\n} from \"./base-list-card-slots\";\n\n/**\n * THE \"LISTA\" LAYOUT'S CARD — {@link BaseCard}'s horizontal sibling.\n *\n * `ListBody` always described the shape it wanted (\"a marker, a title, a\n * subtitle and a value on the right\") and never provided it, so every host\n * hand-rolled a `<Box>` flex row: a tint for selection with no checkbox, fixed\n * `minWidth` columns that ignored density and never collapsed, no hover, no\n * focus ring, and a `borderBottom` fighting the gap between rows.\n *\n * THE LIST OWNS THE COLUMNS. Inside a {@link ListCardGroup} this card is\n * `grid-template-columns: subgrid` across the group's rails, so the value sits\n * on its own edge and cannot be shunted about by the width of the status chip\n * beside it. Standalone it falls back to the same template on its own. See\n * `list-card-rails`.\n *\n * IT ANSWERS ITS OWN WIDTH, not the viewport — a container query, because the\n * same row renders full-bleed on a phone, in a 300px board column, and beside a\n * filter panel that opens and closes. Below `STACK_BREAK` it leaves the shared\n * rails entirely and goes two-line, which is the standard mobile transaction\n * row and beats truncating everything: title + value, then subtitle + status.\n */\n\nexport interface BaseListCardProps extends CardSurfaceProps {\n /** A marker: avatar, thumbnail or status glyph. Earn the pixels — a generic\n * icon repeated down fifty rows is noise. */\n leading?: ReactNode;\n /** First-class title. Rendered as the link when `href` is set. */\n title?: ReactNode;\n /** Secondary line under the title. */\n subtitle?: ReactNode;\n /**\n * Middle columns as labelled pairs — {@link DescriptionItem}s, not free-form\n * nodes, so a screen reader reads \"Data, 05/08/2026\" rather than four\n * unrelated strings. Stacked (label above value) by default.\n *\n * The FIRST rung of the collapse ladder: the only slot whose absence does not\n * stop the row being identified or acted on.\n */\n meta?: DescriptionItemProps[];\n /** Escape hatch for a middle section these pairs cannot express. */\n metaSlot?: ReactNode;\n /** The number this row is about. Its own rail, tabular figures, never truncated. */\n value?: ReactNode;\n /**\n * Inline actions — the one or two things done often enough to deserve a\n * button. Revealed on hover and `:focus-within` by default, so fifty rows of\n * buttons are not the resting state of the page.\n */\n actions?: ReactNode;\n /** Always show the inline actions, rather than on hover/focus. */\n actionsAlwaysVisible?: boolean;\n /** The 3-dots overflow menu, pinned to the end. Also opens on right-click. */\n menu?: ReactNode;\n /** What opens the overflow menu on right-click / long-press. */\n onContextMenu?: (event: React.MouseEvent) => void;\n /**\n * THE EXPANDABLE BODY — and the whole reason this is a card and not a table\n * row.\n *\n * A summary row of labelled columns is a table row with a border round it: it\n * restates what the table already says and gives nobody a reason to switch to\n * it. What a card can do that a table cell cannot is OPEN — carry the record's\n * own detail underneath its summary, in whatever shape that record wants.\n *\n * So this container makes no claim about what goes in here. It spans every\n * rail and imposes nothing: an order puts its line items and a totals ledger\n * here, a cart adds its recovery actions, a role lists its permissions. The\n * design of that area belongs entirely to the consumer, and none of it is the\n * envelope's business.\n *\n * ABSENT ⇒ NO CHEVRON. A row given nothing to reveal renders no disclosure\n * control at all, rather than one that opens onto an empty box, so a column of\n * chevrons is a truthful index of which rows have more behind them.\n */\n children?: ReactNode;\n /** Open on first render, for an uncontrolled card. Ignored when `expanded` is set. */\n defaultExpanded?: boolean;\n /**\n * Open state, when the LIST wants to own it.\n *\n * Left unset the card keeps its own, and rows open independently — several at\n * once, which is what comparing two records requires. Pass this (with\n * `onExpandedChange`) to impose something else, an accordion being the usual\n * reason.\n */\n expanded?: boolean;\n /** Fired with the state the card is asking to move to. */\n onExpandedChange?: (expanded: boolean) => void;\n /** Toggle this row's selection. Receives the raw event so a list can range-select. */\n onToggleSelect?: (event?: React.MouseEvent) => void;\n /** How much air the row gets. Vertical only — a full-width row cannot narrow. */\n density?: DataViewsDensity;\n /**\n * Fine-grained size multiplier on top of `density` (1 = base).\n *\n * Applied as `zoom`, so it scales EVERYTHING the row draws — type, gutters,\n * gaps, padding, the checkbox, the grip, the chip and the menu — not just the\n * handful of font sizes it once multiplied.\n */\n scale?: number;\n /** Flush style: a bottom rule instead of an outline. Row-only. */\n divider?: boolean;\n /** This row's id for drag purposes. Inert outside a `DragContainerProvider`. */\n dragId?: string | number;\n /**\n * The record this row is about, read by the list's cell config.\n *\n * Required only when cells are configured — the config's `primary`/`secondary`\n * are functions of the row, so without one there is nothing to render them\n * from and the card falls back to its named slots.\n */\n row?: Record<string, unknown>;\n /**\n * A cell config for a STANDALONE card.\n *\n * Inside a `ListCardGroup` the list's config wins and this is ignored: one\n * declaration of the list's shape is the whole point, and a row permitted to\n * override it could put its columns somewhere no other row has them.\n */\n cells?: readonly ListCardCellConfig<never>[];\n}\n\n\n\n\n/**\n * Which cell config applies, and whether this row resolves its own tracks.\n *\n * The list's config wins over the card's: one declaration of the list's shape is\n * the point, so a row inside a group cannot introduce a column of its own. And\n * the template is standalone-only — inside a group the GROUP owns it and the row\n * is subgrid over it, because a row resolving its own tracks is exactly what\n * stops a list from lining up.\n */\nfunction useResolvedCells(\n props: BaseListCardProps,\n inGroup: boolean,\n): {\n cells: readonly ListCardCellConfig<never>[] | null;\n configured: boolean;\n cellTemplate: string | null;\n} {\n const groupCells = useCellConfig();\n const cells = groupCells ?? props.cells ?? null;\n const configured = cells != null && cells.length > 0 && props.row != null;\n const cellTemplate = configured && !inGroup ? cellRailsTemplate(cellTracks(cells)) : null;\n return { cells, configured, cellTemplate };\n}\n\n\n/**\n * The row's middle: either the list's configured cells, or the named slots.\n *\n * Split out because the branch is the only conditional shape the card has, and\n * inlined it pushed `BaseListCard` past both the line and the complexity gate.\n */\nfunction RowContent({\n card,\n cells,\n configured,\n slot,\n actionable,\n meta,\n}: {\n card: BaseListCardProps;\n cells: readonly ListCardCellConfig<never>[] | null;\n configured: boolean;\n slot: (name: string) => string | undefined;\n actionable: boolean;\n meta: { columns: number; present: boolean };\n}): React.JSX.Element {\n if (configured && cells != null) {\n return (\n <>\n {/* The list's columns, rendered from this row. */}\n <ListCardCells cells={cells} row={card.row as never} />\n {/* THE MENU IS NOT PART OF THE CONFIG and never optional: it is where a\n * row's actions live, and a list that folded it into a cell would have\n * nowhere left to put them. So it brackets the cells on its own rail,\n * exactly as the gutters do at the other end. */}\n <ListCardActions\n actions={actionable ? card.actions : undefined}\n alwaysVisible={card.actionsAlwaysVisible}\n menu={card.menu}\n testId={slot}\n />\n </>\n );\n }\n return (\n <>\n <ListCardCaption\n title={card.title}\n subtitle={card.subtitle}\n href={card.href}\n target={card.target}\n testId={slot(\"title\")}\n />\n <ListCardMeta meta={card.meta} metaSlot={card.metaSlot} trailingRule={card.value != null} />\n <ListCardTail\n value={card.value}\n separated={meta.present}\n actions={actionable ? card.actions : undefined}\n actionsAlwaysVisible={card.actionsAlwaysVisible}\n menu={card.menu}\n testId={slot}\n />\n </>\n );\n}\n\n/**\n * The revealed body, and the rule that separates it from the summary.\n *\n * `gridColumn: 1 / -1` so it spans every rail: the summary's columns are the\n * LIST's, and nothing about them should constrain a detail area whose design\n * belongs to the consumer.\n *\n * Collapse rather than an unmount, so the body animates open and keeps its own\n * state between peeks — a consumer putting a form or a scrolled table in here\n * would otherwise have it reset on every toggle. `unmountOnExit` is deliberately\n * NOT set: fifty closed rows pay for fifty hidden subtrees, which is the trade\n * taken because the alternative re-runs every consumer's effects per toggle.\n */\nfunction ExpandableBody({\n disclosure,\n padY,\n pad,\n children,\n}: {\n disclosure: { expandable: boolean; expanded: boolean; regionId: string };\n padY: number;\n pad: number;\n children: ReactNode;\n}): React.JSX.Element {\n if (!disclosure.expandable) return <></>;\n return (\n <Box sx={{ gridColumn: \"1 / -1\", minWidth: 0 }}>\n <Collapse in={disclosure.expanded} timeout={150}>\n <Box\n id={disclosure.regionId}\n role=\"region\"\n sx={{\n minWidth: 0,\n // `padY`, not a fraction of the horizontal padding. The card's own\n // `py` wraps the summary AND the body, so once the body is in flow\n // the summary has no bottom padding of its own — at `comfortable`\n // the row visibly lost the height it had while closed.\n mt: padY,\n pt: padY,\n // A RULE BETWEEN SUMMARY AND BODY, bled through the row's horizontal\n // padding so it spans the card edge to edge. Inset, it reads as a\n // border around the content rather than a division of the card.\n borderTop: 1,\n borderColor: \"divider\",\n mx: -pad,\n px: pad,\n }}\n >\n {children}\n </Box>\n </Collapse>\n </Box>\n );\n}\n\nexport function BaseListCard(props: BaseListCardProps): React.JSX.Element {\n const { selected = false, onClick } = props;\n const shell = useRowShell(props);\n const { actionable, selectable, slot, drag, reserve, pad, padY, acts } = shell;\n const meta = metaShape(props);\n const disclosure = useDisclosure(props);\n const { cells, configured, cellTemplate } = useResolvedCells(props, shell.group != null);\n\n return (\n <Card\n variant=\"outlined\"\n className={props.className}\n dataTestId={props.testId}\n aria-label={props[\"aria-label\"]}\n aria-disabled={actionable ? undefined : true}\n onContextMenu={props.onContextMenu}\n {...(acts ? actionProps(onClick) : {})}\n {...drag.itemProps}\n // A PLAIN OBJECT: `Card` merges by spreading, so a function sx vanishes.\n sx={rowStyles(props, shell, cellTemplate)}\n >\n {drag.dropEdge != null && <DropIndicator edge={drag.dropEdge} />}\n <DiscloseSlot\n expandable={disclosure.expandable}\n expanded={disclosure.expanded}\n reserve={reserve}\n onToggle={disclosure.toggle}\n controls={disclosure.regionId}\n testId={slot(\"disclose\")}\n />\n <DragSlot drag={drag} reserve={reserve} testId={slot(\"drag\")} />\n <SelectSlot\n selectable={selectable}\n selected={selected}\n reserve={reserve}\n onToggleSelect={props.onToggleSelect}\n testId={slot(\"checkbox\")}\n />\n <Box data-slot=\"leading\" sx={{ display: \"flex\", alignItems: \"center\" }}>\n {props.leading}\n </Box>\n <RowContent card={props} cells={cells} configured={configured} slot={slot} actionable={actionable} meta={meta} />\n <ExpandableBody disclosure={disclosure} padY={padY} pad={pad}>\n {props.children}\n </ExpandableBody>\n </Card>\n );\n}\n\nexport { META_BREAK, STACK_BREAK } from \"./base-list-card-slots\";\n"],"mappings":"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","names":["default"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/Chart/chart-format.ts"],"sourcesContent":["import type { ChartNumberFormat } from './ChartSpec.types';\n\nconst formatters: Record<ChartNumberFormat, Intl.NumberFormat> = {\n brl: new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }),\n percent: new Intl.NumberFormat('pt-BR', { style: 'percent', maximumFractionDigits: 1 }),\n compact: new Intl.NumberFormat('pt-BR', { notation: 'compact', maximumFractionDigits: 1 }),\n integer: new Intl.NumberFormat('pt-BR', { maximumFractionDigits: 0 }),\n decimal: new Intl.NumberFormat('pt-BR', { maximumFractionDigits: 2 }),\n};\n\n/**\n * Format a chart value with one of the serializable number formats.\n * `brl` expects integer centavos (repo-wide money convention); `percent`\n * expects a fraction (0.15 → \"15%\"). Non-finite values render as an empty\n * string so a null-ish row never draws \"NaN\" into a tooltip or axis.\n */\nexport function formatChartValue(value: number, format: ChartNumberFormat = 'decimal'): string {\n if (!Number.isFinite(value)) return '';\n if (format === 'brl') return formatters.brl.format(value / 100);\n return formatters[format].format(value);\n}\n\n/** Curried {@link formatChartValue}, memo-friendly for tooltip/axis props. */\nexport function chartValueFormatter(format?: ChartNumberFormat): (value: number) => string {\n return (value: number) => formatChartValue(value, format);\n}\n"],"mappings":";AAEA,IAAM,aAA2D;AAAA,EAC/D,KAAK,IAAI,KAAK,aAAa,SAAS,EAAE,OAAO,YAAY,UAAU,MAAM,CAAC;AAAA,EAC1E,SAAS,IAAI,KAAK,aAAa,SAAS,EAAE,OAAO,WAAW,uBAAuB,EAAE,CAAC;AAAA,EACtF,SAAS,IAAI,KAAK,aAAa,SAAS,EAAE,UAAU,WAAW,uBAAuB,EAAE,CAAC;AAAA,EACzF,SAAS,IAAI,KAAK,aAAa,SAAS,EAAE,uBAAuB,EAAE,CAAC;AAAA,EACpE,SAAS,IAAI,KAAK,aAAa,SAAS,EAAE,uBAAuB,EAAE,CAAC;AACtE;AAQO,SAAS,iBAAiB,OAAe,SAA4B,WAAmB;AAC7F,MAAI,CAAC,OAAO,SAAS,KAAK,EAAG,QAAO;AACpC,MAAI,WAAW,MAAO,QAAO,WAAW,IAAI,OAAO,QAAQ,GAAG;AAC9D,SAAO,WAAW,MAAM,EAAE,OAAO,KAAK;AACxC;AAGO,SAAS,oBAAoB,QAAuD;AACzF,SAAO,CAAC,UAAkB,iBAAiB,OAAO,MAAM;AAC1D;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/Chart/chart-spec.ts"],"sourcesContent":["import type { ChartDataPoint, ChartProps } from './Chart.types';\nimport type { ChartSemanticColor, ChartSpec, ChartSpecSeries } from './ChartSpec.types';\nimport { chartValueFormatter } from './chart-format';\nimport {\n getChartSpecRenderer,\n getRegisteredChartSpecTypes,\n type ChartSpecRenderContext,\n} from './chart-spec-registry';\n\n/**\n * BREAKING FOR STORED SPECS, not just for types.\n *\n * A chart spec is DATA — it is authored as JSON and can be persisted — and this\n * list is validated at runtime, so a saved spec carrying `\"error\"` now throws\n * `ChartSpecError` instead of silently drawing. That is the right failure (the\n * alternative is a series quietly losing its colour), but unlike the rest of\n * this migration a type-check will not find the affected specs: anything stored\n * outside the repo has to be rewritten `error` → `danger`.\n */\nexport const CHART_SEMANTIC_COLORS: readonly ChartSemanticColor[] = [\n 'primary',\n 'secondary',\n 'success',\n 'warning',\n 'danger',\n 'info',\n];\n\nconst NUMBER_FORMATS = ['brl', 'percent', 'compact', 'integer', 'decimal'];\n\n/** Error thrown when an unknown/invalid spec is parsed. Message is written to\n * be actionable for programmatic authors (builders, LLMs). */\nexport class ChartSpecError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ChartSpecError';\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction assertColor(value: unknown, where: string): void {\n if (value === undefined) return;\n if (!CHART_SEMANTIC_COLORS.includes(value as ChartSemanticColor)) {\n throw new ChartSpecError(\n `${where} must be a semantic color token (${CHART_SEMANTIC_COLORS.join(', ')}), got ${JSON.stringify(value)}. Raw color values are not allowed.`,\n );\n }\n}\n\nfunction parseAxis(value: unknown): { key: string; label?: string } {\n if (!isRecord(value) || typeof value.key !== 'string' || value.key.length === 0) {\n throw new ChartSpecError('\"xAxis\" must be an object with a non-empty string \"key\" naming the row property for the category axis.');\n }\n if (value.label !== undefined && typeof value.label !== 'string') {\n throw new ChartSpecError('\"xAxis.label\" must be a string when provided.');\n }\n return { key: value.key, label: value.label };\n}\n\nfunction parseSeries(value: unknown): ChartSpecSeries[] {\n if (!Array.isArray(value) || value.length === 0) {\n throw new ChartSpecError('\"series\" must be a non-empty array of { key, label?, color? } objects.');\n }\n return value.map((entry, index) => {\n if (!isRecord(entry) || typeof entry.key !== 'string' || entry.key.length === 0) {\n throw new ChartSpecError(`\"series[${index}]\" must be an object with a non-empty string \"key\" naming the row property holding its values.`);\n }\n assertColor(entry.color, `\"series[${index}].color\"`);\n if (entry.label !== undefined && typeof entry.label !== 'string') {\n throw new ChartSpecError(`\"series[${index}].label\" must be a string when provided.`);\n }\n return { key: entry.key, label: entry.label, color: entry.color as ChartSemanticColor | undefined };\n });\n}\n\nfunction assertFieldType(\n spec: Record<string, unknown>,\n field: string,\n expected: 'string' | 'boolean' | 'number',\n): void {\n const value = spec[field];\n if (value !== undefined && typeof value !== expected) {\n throw new ChartSpecError(`\"${field}\" must be a ${expected} when provided.`);\n }\n}\n\nfunction parseColorScheme(value: unknown): ChartSemanticColor[] | undefined {\n if (value === undefined) return undefined;\n if (!Array.isArray(value) || value.length === 0) {\n throw new ChartSpecError('\"colorScheme\" must be a non-empty array of semantic color tokens when provided.');\n }\n value.forEach((token, index) => assertColor(token, `\"colorScheme[${index}]\"`));\n return value as ChartSemanticColor[];\n}\n\nfunction parseOptionalFields(spec: Record<string, unknown>): Partial<ChartSpec> {\n for (const field of ['title', 'subtitle'] as const) assertFieldType(spec, field, 'string');\n for (const field of ['stacked', 'legend', 'tooltip', 'curved'] as const) {\n assertFieldType(spec, field, 'boolean');\n }\n assertFieldType(spec, 'height', 'number');\n if (spec.numberFormat !== undefined && !NUMBER_FORMATS.includes(spec.numberFormat as string)) {\n throw new ChartSpecError(\n `\"numberFormat\" must be one of ${NUMBER_FORMATS.join(', ')}, got ${JSON.stringify(spec.numberFormat)}.`,\n );\n }\n return {\n title: spec.title as string | undefined,\n subtitle: spec.subtitle as string | undefined,\n stacked: spec.stacked as boolean | undefined,\n legend: spec.legend as boolean | undefined,\n tooltip: spec.tooltip as boolean | undefined,\n curved: spec.curved as boolean | undefined,\n height: spec.height as number | undefined,\n numberFormat: spec.numberFormat as ChartSpec['numberFormat'],\n colorScheme: parseColorScheme(spec.colorScheme),\n };\n}\n\n/**\n * Validate an untrusted value (e.g. JSON from storage or an LLM) into a\n * `ChartSpec`. Throws {@link ChartSpecError} with an actionable message on\n * the first problem found.\n */\nexport function parseChartSpec(input: unknown): ChartSpec {\n if (!isRecord(input)) {\n throw new ChartSpecError('A chart spec must be a JSON object.');\n }\n const type = input.type;\n if (typeof type !== 'string' || !getChartSpecRenderer(type)) {\n throw new ChartSpecError(\n `\"type\" must be one of the registered chart types (${getRegisteredChartSpecTypes().join(', ')}), got ${JSON.stringify(type)}.`,\n );\n }\n const yAxis = input.yAxis;\n if (yAxis !== undefined && (!isRecord(yAxis) || (yAxis.label !== undefined && typeof yAxis.label !== 'string'))) {\n throw new ChartSpecError('\"yAxis\" must be an object with an optional string \"label\" when provided.');\n }\n const centerLabel = input.centerLabel;\n return {\n ...parseOptionalFields(input),\n type: type as ChartSpec['type'],\n xAxis: parseAxis(input.xAxis),\n yAxis: yAxis as ChartSpec['yAxis'],\n series: parseSeries(input.series),\n centerLabel: centerLabel as ChartSpec['centerLabel'],\n };\n}\n\n/**\n * Derive the prop-driven `Chart` props for a validated spec. The spec API is\n * layered on top of the existing component — one rendering implementation.\n */\nexport function specToChartProps(\n spec: ChartSpec,\n data: ChartDataPoint[],\n ctx: ChartSpecRenderContext,\n): ChartProps {\n const renderer = getChartSpecRenderer(spec.type);\n if (!renderer) {\n throw new ChartSpecError(\n `Unknown chart type \"${spec.type}\". Registered types: ${getRegisteredChartSpecTypes().join(', ')}.`,\n );\n }\n return {\n data,\n title: spec.title,\n subtitle: spec.subtitle,\n xAxisKey: spec.xAxis.key,\n xAxisLabel: spec.xAxis.label,\n yAxisLabel: spec.yAxis?.label,\n showLegend: spec.legend ?? true,\n showTooltip: spec.tooltip ?? true,\n height: spec.height,\n valueFormatter: chartValueFormatter(spec.numberFormat),\n // An integer metric is a COUNT: half a row does not exist, so the axis must\n // not offer half-steps it would then round into duplicates (FUT-755).\n allowDecimalTicks: spec.numberFormat !== 'integer',\n ...renderer(spec, ctx),\n };\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/Chart/chart-renderers.tsx"],"sourcesContent":["import type { Theme } from '@mui/material/styles/index.js';\nimport React from 'react';\nimport {\n Area,\n AreaChart,\n Bar,\n BarChart,\n CartesianGrid,\n Cell,\n ComposedChart,\n Legend,\n Line,\n LineChart,\n Pie,\n PieChart,\n PolarAngleAxis,\n PolarGrid,\n PolarRadiusAxis,\n Radar,\n RadarChart,\n Scatter,\n ScatterChart,\n Tooltip,\n XAxis,\n YAxis,\n} from 'recharts';\n\nimport type { ChartProps, ChartSeries } from './Chart.types';\nimport { ChartLegendContent, ChartTooltipContent } from './ChartComposables';\nimport { buildChartContext, type ChartRenderContext } from './chart-context';\nimport { uiInk } from '../../../tokens/ink';\nimport { remPx } from '../../../tokens/relative';\n\n/**\n * Per-type Recharts renderers for the prop-driven Chart, dispatched from a\n * registry keyed by `ChartProps['type']`. Each renderer reads a prepared\n * {@link ChartRenderContext} so every function stays small.\n */\n\nfunction chartExtras(ctx: ChartRenderContext): React.ReactNode[] {\n const { props } = ctx;\n const nodes: React.ReactNode[] = [];\n if (props.showTooltip !== false) {\n nodes.push(\n <Tooltip key=\"tooltip\" content={<ChartTooltipContent valueFormatter={props.valueFormatter} />} />,\n );\n }\n if (props.showLegend !== false) {\n nodes.push(<Legend key=\"legend\" content={<ChartLegendContent />} />);\n }\n return nodes;\n}\n\n/**\n * Gridlines: solid, and one step below the card border. A dashed line at the\n * border's own weight competes with the data drawn over it.\n */\nfunction chartGrid(ctx: ChartRenderContext): React.ReactElement {\n return <CartesianGrid key=\"grid\" stroke={ctx.gridStroke} strokeOpacity={ctx.gridOpacity} />;\n}\n\nfunction cartesianAxes(ctx: ChartRenderContext): React.ReactNode[] {\n const { props, axisConfig } = ctx;\n const nodes: React.ReactNode[] = [];\n if (props.showCartesianGrid !== false) nodes.push(chartGrid(ctx));\n nodes.push(\n <XAxis\n key=\"x\"\n dataKey={props.xAxisKey ?? 'name'}\n style={ctx.axisStyle}\n label={props.xAxisLabel}\n tickMargin={axisConfig.tickMargin}\n ticks={axisConfig.categoryTicks}\n tickFormatter={axisConfig.tickFormatter}\n />,\n <YAxis\n key=\"y\"\n style={ctx.axisStyle}\n label={props.yAxisLabel}\n // Sized from its own widest tick: a fixed 60px lets \"R$ 1.234,56\" spill\n // out of the card, which is the other way axis text ends up on top of\n // something.\n width=\"auto\"\n tickMargin={axisConfig.tickMargin}\n tickFormatter={props.valueFormatter}\n allowDecimals={props.allowDecimalTicks !== false}\n />,\n );\n return nodes;\n}\n\nfunction renderLine(ctx: ChartRenderContext): React.ReactElement {\n return (\n <LineChart {...ctx.commonProps}>\n {cartesianAxes(ctx)}\n {chartExtras(ctx)}\n {ctx.chartSeries.map((s, index) => (\n <Line\n key={s.dataKey}\n type={ctx.strokeType}\n dataKey={s.dataKey}\n name={s.name}\n stroke={s.color ?? ctx.chartColors[index % ctx.chartColors.length]}\n strokeWidth={s.strokeWidth ?? 2}\n dot={s.dot !== false}\n activeDot={s.activeDot !== false ? { r: 8 } : false}\n animationDuration={ctx.animationDuration}\n />\n ))}\n </LineChart>\n );\n}\n\nfunction renderBar(ctx: ChartRenderContext): React.ReactElement {\n return (\n <BarChart {...ctx.commonProps}>\n {cartesianAxes(ctx)}\n {chartExtras(ctx)}\n {ctx.chartSeries.map((s, index) => (\n <Bar\n key={s.dataKey}\n dataKey={s.dataKey}\n name={s.name}\n fill={s.fill ?? s.color ?? ctx.chartColors[index % ctx.chartColors.length]}\n stackId={ctx.props.stacked ? 'stack' : undefined}\n radius={ctx.barGeometry.radius}\n maxBarSize={ctx.barGeometry.maxBarSize}\n animationDuration={ctx.animationDuration}\n />\n ))}\n </BarChart>\n );\n}\n\nfunction renderArea(ctx: ChartRenderContext): React.ReactElement {\n return (\n <AreaChart {...ctx.commonProps}>\n {cartesianAxes(ctx)}\n {chartExtras(ctx)}\n {ctx.chartSeries.map((s, index) => (\n <Area\n key={s.dataKey}\n type={ctx.strokeType}\n dataKey={s.dataKey}\n name={s.name}\n stroke={s.color ?? ctx.chartColors[index % ctx.chartColors.length]}\n fill={s.fill ?? s.color ?? ctx.chartColors[index % ctx.chartColors.length]}\n fillOpacity={s.fillOpacity ?? 0.6}\n stackId={ctx.props.stacked ? 'stack' : undefined}\n animationDuration={ctx.animationDuration}\n />\n ))}\n </AreaChart>\n );\n}\n\nfunction pieCenterLabel(ctx: ChartRenderContext): React.ReactNode {\n const { centerLabel } = ctx.props;\n const innerRadius = ctx.props.innerRadius ?? 0;\n if (!centerLabel || innerRadius <= 0) return null;\n const fill = ctx.props.variant === 'neon' ? uiInk(ctx.theme).dataVizNeon.accent : ctx.theme.palette.text.primary;\n return (\n <text\n x=\"50%\"\n y=\"50%\"\n textAnchor=\"middle\"\n dominantBaseline=\"middle\"\n style={{ fontSize: ctx.sizeStyles.fontSize, fill, fontWeight: 600 }}\n >\n {typeof centerLabel === 'string' ? (\n centerLabel\n ) : (\n <>\n <tspan\n x=\"50%\"\n dy=\"-0.6em\"\n style={{ fontSize: '0.875em', fontWeight: 500, fill: ctx.theme.palette.text.secondary }}\n >\n {centerLabel.label}\n </tspan>\n <tspan x=\"50%\" dy=\"1.4em\" style={{ fontSize: '1.5em', fontWeight: 700 }}>\n {centerLabel.value}\n </tspan>\n </>\n )}\n </text>\n );\n}\n\nfunction renderPie(ctx: ChartRenderContext): React.ReactElement {\n const { props } = ctx;\n return (\n <PieChart>\n {chartExtras(ctx)}\n <Pie\n data={props.data}\n dataKey={ctx.chartSeries[0]?.dataKey ?? 'value'}\n nameKey={props.xAxisKey ?? 'name'}\n cx=\"50%\"\n cy=\"50%\"\n outerRadius={ctx.sizeStyles.height / 3}\n innerRadius={remPx(ctx.theme, props.innerRadius ?? 0)}\n fill={ctx.chartColors[0]}\n label={props.showValues ?? false}\n animationDuration={ctx.animationDuration}\n >\n {props.data.map((entry, index) => (\n <Cell key={`cell-${index}`} fill={ctx.chartColors[index % ctx.chartColors.length]} />\n ))}\n </Pie>\n {pieCenterLabel(ctx)}\n </PieChart>\n );\n}\n\nfunction renderRadar(ctx: ChartRenderContext): React.ReactElement {\n return (\n <RadarChart {...ctx.commonProps}>\n <PolarGrid stroke={ctx.gridStroke} />\n <PolarAngleAxis dataKey={ctx.props.xAxisKey ?? 'name'} style={ctx.axisStyle} />\n <PolarRadiusAxis style={ctx.axisStyle} />\n {chartExtras(ctx)}\n {ctx.chartSeries.map((s, index) => (\n <Radar\n key={s.dataKey}\n dataKey={s.dataKey}\n name={s.name}\n stroke={s.color ?? ctx.chartColors[index % ctx.chartColors.length]}\n fill={s.fill ?? s.color ?? ctx.chartColors[index % ctx.chartColors.length]}\n fillOpacity={s.fillOpacity ?? 0.6}\n animationDuration={ctx.animationDuration}\n />\n ))}\n </RadarChart>\n );\n}\n\nfunction renderScatter(ctx: ChartRenderContext): React.ReactElement {\n const { props } = ctx;\n return (\n <ScatterChart {...ctx.commonProps}>\n {props.showCartesianGrid !== false && chartGrid(ctx)}\n <XAxis\n dataKey={props.xAxisKey ?? 'name'}\n style={ctx.axisStyle}\n label={props.xAxisLabel}\n tickMargin={ctx.axisConfig.tickMargin}\n />\n <YAxis\n dataKey={ctx.chartSeries[0]?.dataKey}\n style={ctx.axisStyle}\n label={props.yAxisLabel}\n tickMargin={ctx.axisConfig.tickMargin}\n />\n {chartExtras(ctx)}\n <Scatter\n name={ctx.chartSeries[0]?.name ?? 'Data'}\n data={props.data}\n fill={ctx.chartColors[0]}\n animationDuration={ctx.animationDuration}\n />\n </ScatterChart>\n );\n}\n\nfunction composedSeries(ctx: ChartRenderContext, s: ChartSeries, index: number): React.ReactElement {\n const color = s.color ?? ctx.chartColors[index % ctx.chartColors.length];\n if (s.type === 'bar') {\n return (\n <Bar\n key={s.dataKey}\n dataKey={s.dataKey}\n name={s.name}\n fill={color}\n radius={ctx.barGeometry.radius}\n maxBarSize={ctx.barGeometry.maxBarSize}\n animationDuration={ctx.animationDuration}\n />\n );\n }\n if (s.type === 'area') {\n return (\n <Area\n key={s.dataKey}\n type={ctx.strokeType}\n dataKey={s.dataKey}\n name={s.name}\n stroke={color}\n fill={color}\n fillOpacity={0.6}\n animationDuration={ctx.animationDuration}\n />\n );\n }\n return (\n <Line\n key={s.dataKey}\n type={ctx.strokeType}\n dataKey={s.dataKey}\n name={s.name}\n stroke={color}\n animationDuration={ctx.animationDuration}\n />\n );\n}\n\nfunction renderComposed(ctx: ChartRenderContext): React.ReactElement {\n return (\n <ComposedChart {...ctx.commonProps}>\n {cartesianAxes(ctx)}\n {chartExtras(ctx)}\n {ctx.chartSeries.map((s, index) => composedSeries(ctx, s, index))}\n </ComposedChart>\n );\n}\n\nconst RENDERERS: Record<string, (ctx: ChartRenderContext) => React.ReactElement> = {\n line: renderLine,\n bar: renderBar,\n area: renderArea,\n pie: renderPie,\n radar: renderRadar,\n scatter: renderScatter,\n composed: renderComposed,\n};\n\n/** Render the Recharts element for the requested chart type. */\nexport function renderChartByType(props: ChartProps, theme: Theme): React.ReactElement {\n const renderer = RENDERERS[props.type ?? 'line'];\n const ctx = buildChartContext(props, theme);\n return renderer ? renderer(ctx) : <></>;\n}\n"],"mappings":"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","names":[]}