@12-apps/ui 6.2.0 → 6.3.1

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 (166) hide show
  1. package/dist/{chunk-35VGGLOC.js → chunk-CEKPLUQV.js} +2 -2
  2. package/dist/{chunk-35VGGLOC.js.map → chunk-CEKPLUQV.js.map} +1 -1
  3. package/dist/{chunk-7XLEWBKL.js → chunk-N554AFDB.js} +7 -10
  4. package/dist/chunk-N554AFDB.js.map +1 -0
  5. package/dist/{chunk-JDO7W4D4.js → chunk-R5ZQZSEQ.js} +2 -20
  6. package/dist/{chunk-JDO7W4D4.js.map → chunk-R5ZQZSEQ.js.map} +1 -1
  7. package/dist/{chunk-R4TYXKDD.js → chunk-TPQRIPCN.js} +52 -48
  8. package/dist/chunk-TPQRIPCN.js.map +1 -0
  9. package/dist/{chunk-62XQWGXU.js → chunk-WFPXRSIZ.js} +20 -18
  10. package/dist/chunk-WFPXRSIZ.js.map +1 -0
  11. package/dist/copy.js +1 -0
  12. package/dist/copy.js.map +1 -0
  13. package/dist/data-display/CardKit.js +15 -4
  14. package/dist/data-display/CardKit.js.map +1 -1
  15. package/dist/data-display/DataViews.js +664 -616
  16. package/dist/data-display/DataViews.js.map +1 -1
  17. package/dist/data-display/SectionOnboarding.js +3 -3
  18. package/dist/data-display/SectionOnboarding.js.map +1 -1
  19. package/dist/feedback/ConfirmAction.js +3 -5
  20. package/dist/form/CategorySelect.js +1 -1
  21. package/dist/form/CepField.js +1 -1
  22. package/dist/form/total-form.js +8 -4
  23. package/dist/form/total-form.js.map +1 -1
  24. package/dist/layout/ContentToolbar.js +1 -1
  25. package/dist/layout/TableFilter.js +1 -1
  26. package/dist/pt-BR.js +222 -0
  27. package/dist/pt-BR.js.map +1 -0
  28. package/dist/types/components/data-display/CardKit/use-remove-confirm.d.ts +4 -1
  29. package/dist/types/components/data-display/CardKit/use-remove-confirm.d.ts.map +1 -1
  30. package/dist/types/components/data-display/CardKit/use-row-confirm.d.ts +5 -2
  31. package/dist/types/components/data-display/CardKit/use-row-confirm.d.ts.map +1 -1
  32. package/dist/types/components/data-display/DataViews/DataViewsBoard.d.ts.map +1 -1
  33. package/dist/types/components/data-display/DataViews/DeleteViewDialog.d.ts.map +1 -1
  34. package/dist/types/components/data-display/DataViews/ManageViewsDialog.d.ts +4 -1
  35. package/dist/types/components/data-display/DataViews/ManageViewsDialog.d.ts.map +1 -1
  36. package/dist/types/components/data-display/DataViews/SaveViewModal.d.ts +0 -5
  37. package/dist/types/components/data-display/DataViews/SaveViewModal.d.ts.map +1 -1
  38. package/dist/types/components/data-display/DataViews/base-card.d.ts.map +1 -1
  39. package/dist/types/components/data-display/DataViews/base-list-card-gutters.d.ts.map +1 -1
  40. package/dist/types/components/data-display/DataViews/data-views-bar-controls.d.ts.map +1 -1
  41. package/dist/types/components/data-display/DataViews/data-views-category-pill.d.ts.map +1 -1
  42. package/dist/types/components/data-display/DataViews/data-views-columns-tab.d.ts.map +1 -1
  43. package/dist/types/components/data-display/DataViews/data-views-copy-context.d.ts +17 -0
  44. package/dist/types/components/data-display/DataViews/data-views-copy-context.d.ts.map +1 -0
  45. package/dist/types/components/data-display/DataViews/data-views-copy.d.ts +205 -0
  46. package/dist/types/components/data-display/DataViews/data-views-copy.d.ts.map +1 -0
  47. package/dist/types/components/data-display/DataViews/data-views-display-panel.d.ts.map +1 -1
  48. package/dist/types/components/data-display/DataViews/data-views-display-tabs.d.ts.map +1 -1
  49. package/dist/types/components/data-display/DataViews/data-views-export.d.ts.map +1 -1
  50. package/dist/types/components/data-display/DataViews/data-views-filter-panel.d.ts.map +1 -1
  51. package/dist/types/components/data-display/DataViews/data-views-grid-helpers.d.ts.map +1 -1
  52. package/dist/types/components/data-display/DataViews/data-views-more-fields.d.ts.map +1 -1
  53. package/dist/types/components/data-display/DataViews/data-views-more-filters.d.ts.map +1 -1
  54. package/dist/types/components/data-display/DataViews/data-views-range-pill.d.ts.map +1 -1
  55. package/dist/types/components/data-display/DataViews/data-views-range-presets.d.ts +3 -2
  56. package/dist/types/components/data-display/DataViews/data-views-range-presets.d.ts.map +1 -1
  57. package/dist/types/components/data-display/DataViews/data-views-scopes.d.ts.map +1 -1
  58. package/dist/types/components/data-display/DataViews/data-views-search.d.ts.map +1 -1
  59. package/dist/types/components/data-display/DataViews/data-views-select-all-strip.d.ts.map +1 -1
  60. package/dist/types/components/data-display/DataViews/data-views-table-parts.d.ts.map +1 -1
  61. package/dist/types/components/data-display/DataViews/data-views-view-nav.d.ts +1 -1
  62. package/dist/types/components/data-display/DataViews/data-views-view-nav.d.ts.map +1 -1
  63. package/dist/types/components/data-display/DataViews/index.d.ts +2 -0
  64. package/dist/types/components/data-display/DataViews/index.d.ts.map +1 -1
  65. package/dist/types/components/data-display/DataViews/save-view-preview.d.ts +10 -0
  66. package/dist/types/components/data-display/DataViews/save-view-preview.d.ts.map +1 -0
  67. package/dist/types/components/data-display/DataViews/use-saved-views-controller.d.ts.map +1 -1
  68. package/dist/types/components/data-display/SectionOnboarding/SectionOnboarding.types.d.ts +6 -5
  69. package/dist/types/components/data-display/SectionOnboarding/SectionOnboarding.types.d.ts.map +1 -1
  70. package/dist/types/components/feedback/ConfirmAction/ConfirmAction.hooks.d.ts +1 -3
  71. package/dist/types/components/feedback/ConfirmAction/ConfirmAction.hooks.d.ts.map +1 -1
  72. package/dist/types/components/feedback/ConfirmAction/ConfirmAction.parts.d.ts +4 -1
  73. package/dist/types/components/feedback/ConfirmAction/ConfirmAction.parts.d.ts.map +1 -1
  74. package/dist/types/components/feedback/ConfirmAction/ConfirmAction.types.d.ts +9 -1
  75. package/dist/types/components/feedback/ConfirmAction/ConfirmAction.types.d.ts.map +1 -1
  76. package/dist/types/components/feedback/ConfirmAction/ConfirmButton.d.ts +2 -1
  77. package/dist/types/components/feedback/ConfirmAction/ConfirmButton.d.ts.map +1 -1
  78. package/dist/types/components/feedback/ConfirmAction/index.d.ts +2 -2
  79. package/dist/types/components/feedback/ConfirmAction/index.d.ts.map +1 -1
  80. package/dist/types/components/feedback/ConfirmAction/with-confirmation.d.ts +5 -1
  81. package/dist/types/components/feedback/ConfirmAction/with-confirmation.d.ts.map +1 -1
  82. package/dist/types/components/form/CategorySelect/CategoryPanel.d.ts +4 -1
  83. package/dist/types/components/form/CategorySelect/CategoryPanel.d.ts.map +1 -1
  84. package/dist/types/components/form/CategorySelect/CategoryPanelFoot.d.ts +5 -2
  85. package/dist/types/components/form/CategorySelect/CategoryPanelFoot.d.ts.map +1 -1
  86. package/dist/types/components/form/CategorySelect/CategoryPanelHead.d.ts +5 -2
  87. package/dist/types/components/form/CategorySelect/CategoryPanelHead.d.ts.map +1 -1
  88. package/dist/types/components/form/CategorySelect/CategoryPanelList.d.ts +3 -0
  89. package/dist/types/components/form/CategorySelect/CategoryPanelList.d.ts.map +1 -1
  90. package/dist/types/components/form/CategorySelect/CategorySelect.types.d.ts +5 -0
  91. package/dist/types/components/form/CategorySelect/CategorySelect.types.d.ts.map +1 -1
  92. package/dist/types/components/form/CategorySelect/CategoryTrigger.d.ts +4 -1
  93. package/dist/types/components/form/CategorySelect/CategoryTrigger.d.ts.map +1 -1
  94. package/dist/types/components/form/CepField/CepField.d.ts +1 -1
  95. package/dist/types/components/form/CepField/CepField.d.ts.map +1 -1
  96. package/dist/types/components/form/CepField/CepField.types.d.ts +3 -0
  97. package/dist/types/components/form/CepField/CepField.types.d.ts.map +1 -1
  98. package/dist/types/components/form/total-form/Fields/CategoryField.d.ts +4 -1
  99. package/dist/types/components/form/total-form/Fields/CategoryField.d.ts.map +1 -1
  100. package/dist/types/components/form/total-form/Fields/CepField.d.ts +4 -1
  101. package/dist/types/components/form/total-form/Fields/CepField.d.ts.map +1 -1
  102. package/dist/types/components/layout/ContentToolbar/ContentToolbar.types.d.ts +6 -1
  103. package/dist/types/components/layout/ContentToolbar/ContentToolbar.types.d.ts.map +1 -1
  104. package/dist/types/components/layout/ContentToolbar/SavedViewsMenu.d.ts.map +1 -1
  105. package/dist/types/copy.d.ts +99 -0
  106. package/dist/types/copy.d.ts.map +1 -0
  107. package/dist/types/pt-BR.d.ts +28 -0
  108. package/dist/types/pt-BR.d.ts.map +1 -0
  109. package/package.json +10 -2
  110. package/src/components/data-display/CardKit/use-remove-confirm.tsx +5 -0
  111. package/src/components/data-display/CardKit/use-row-confirm.tsx +7 -2
  112. package/src/components/data-display/DataViews/DataViewsBoard.tsx +7 -4
  113. package/src/components/data-display/DataViews/DeleteViewDialog.tsx +6 -4
  114. package/src/components/data-display/DataViews/ManageViewsDialog.tsx +26 -10
  115. package/src/components/data-display/DataViews/SaveViewModal.tsx +56 -90
  116. package/src/components/data-display/DataViews/base-card.tsx +3 -1
  117. package/src/components/data-display/DataViews/base-list-card-gutters.tsx +3 -1
  118. package/src/components/data-display/DataViews/data-views-bar-controls.tsx +8 -5
  119. package/src/components/data-display/DataViews/data-views-category-pill.tsx +6 -3
  120. package/src/components/data-display/DataViews/data-views-columns-tab.tsx +5 -3
  121. package/src/components/data-display/DataViews/data-views-copy-context.tsx +43 -0
  122. package/src/components/data-display/DataViews/data-views-copy.ts +214 -0
  123. package/src/components/data-display/DataViews/data-views-display-panel.tsx +15 -9
  124. package/src/components/data-display/DataViews/data-views-display-tabs.tsx +19 -29
  125. package/src/components/data-display/DataViews/data-views-export.tsx +9 -10
  126. package/src/components/data-display/DataViews/data-views-filter-panel.tsx +9 -5
  127. package/src/components/data-display/DataViews/data-views-grid-helpers.tsx +5 -2
  128. package/src/components/data-display/DataViews/data-views-more-fields.tsx +5 -3
  129. package/src/components/data-display/DataViews/data-views-more-filters.tsx +6 -3
  130. package/src/components/data-display/DataViews/data-views-range-pill.tsx +9 -5
  131. package/src/components/data-display/DataViews/data-views-range-presets.ts +7 -8
  132. package/src/components/data-display/DataViews/data-views-scopes.tsx +3 -1
  133. package/src/components/data-display/DataViews/data-views-search.tsx +7 -4
  134. package/src/components/data-display/DataViews/data-views-select-all-strip.tsx +5 -3
  135. package/src/components/data-display/DataViews/data-views-table-parts.tsx +7 -2
  136. package/src/components/data-display/DataViews/data-views-view-nav.tsx +22 -16
  137. package/src/components/data-display/DataViews/index.ts +20 -0
  138. package/src/components/data-display/DataViews/save-view-preview.tsx +78 -0
  139. package/src/components/data-display/DataViews/use-saved-views-controller.ts +3 -1
  140. package/src/components/data-display/SectionOnboarding/SectionOnboarding.tsx +3 -3
  141. package/src/components/data-display/SectionOnboarding/SectionOnboarding.types.ts +8 -7
  142. package/src/components/feedback/ConfirmAction/ConfirmAction.hooks.ts +2 -2
  143. package/src/components/feedback/ConfirmAction/ConfirmAction.parts.tsx +20 -6
  144. package/src/components/feedback/ConfirmAction/ConfirmAction.types.ts +9 -1
  145. package/src/components/feedback/ConfirmAction/ConfirmButton.tsx +12 -4
  146. package/src/components/feedback/ConfirmAction/index.ts +2 -2
  147. package/src/components/feedback/ConfirmAction/with-confirmation.tsx +4 -3
  148. package/src/components/form/CategorySelect/CategoryPanel.tsx +18 -6
  149. package/src/components/form/CategorySelect/CategoryPanelFoot.tsx +10 -5
  150. package/src/components/form/CategorySelect/CategoryPanelHead.tsx +8 -3
  151. package/src/components/form/CategorySelect/CategoryPanelList.tsx +17 -10
  152. package/src/components/form/CategorySelect/CategorySelect.tsx +3 -3
  153. package/src/components/form/CategorySelect/CategorySelect.types.ts +5 -0
  154. package/src/components/form/CategorySelect/CategoryTrigger.tsx +5 -1
  155. package/src/components/form/CepField/CepField.tsx +6 -9
  156. package/src/components/form/CepField/CepField.types.ts +3 -0
  157. package/src/components/form/total-form/Fields/CategoryField.tsx +5 -0
  158. package/src/components/form/total-form/Fields/CepField.tsx +5 -0
  159. package/src/components/layout/ContentToolbar/ContentToolbar.types.ts +6 -1
  160. package/src/components/layout/ContentToolbar/SavedViewsMenu.tsx +1 -21
  161. package/src/components/layout/TableFilter/TableFilter.tsx +1 -1
  162. package/src/copy.ts +103 -0
  163. package/src/pt-BR.ts +247 -0
  164. package/dist/chunk-62XQWGXU.js.map +0 -1
  165. package/dist/chunk-7XLEWBKL.js.map +0 -1
  166. package/dist/chunk-R4TYXKDD.js.map +0 -1
@@ -7,6 +7,7 @@ import { TableFilter } from "../../layout/TableFilter";
7
7
 
8
8
  import { PillControl } from "./data-views-category-pill";
9
9
  import { PanelRangeField } from "./data-views-range-pill";
10
+ import { useDataViewsCopy } from "./data-views-copy-context";
10
11
  import type {
11
12
  FilterFieldConfig,
12
13
  RangeFieldConfig,
@@ -84,17 +85,18 @@ function FilterControls<T extends Record<string, unknown>>({
84
85
  onChangeRange,
85
86
  onClearField,
86
87
  }: Omit<GridFilterPanelProps<T>, "onClearAll">): React.JSX.Element {
88
+ const copy = useDataViewsCopy();
87
89
  return (
88
90
  <>
89
91
  <TableFilter.Keyword
90
92
  value={search}
91
93
  onChange={onSearchChange}
92
- label="Buscar em todas as colunas"
93
- placeholder="Pressione Enter para filtrar"
94
+ label={copy.search.allColumnsLabel}
95
+ placeholder={copy.search.keywordPlaceholder}
94
96
  testId={`${testIdPrefix}-search-all`}
95
97
  />
96
98
  {(fields.length > 0 || rangeFields.length > 0) && (
97
- <TableFilter.Section title="Filtros">
99
+ <TableFilter.Section title={copy.filters.panelTitle}>
98
100
  {fields.map((field) => (
99
101
  <PillField
100
102
  key={field.id}
@@ -124,11 +126,12 @@ function FilterControls<T extends Record<string, unknown>>({
124
126
  export function GridFilterPanel<T extends Record<string, unknown>>(
125
127
  props: GridFilterPanelProps<T>,
126
128
  ): React.JSX.Element {
129
+ const copy = useDataViewsCopy();
127
130
  return (
128
131
  <TableFilter.Panel
129
132
  onClearAll={props.onClearAll}
130
133
  clearTestId={`${props.testIdPrefix}-clear-filters`}
131
- ariaLabel="Filtros"
134
+ ariaLabel={copy.filters.panelTitle}
132
135
  >
133
136
  <FilterControls {...props} />
134
137
  </TableFilter.Panel>
@@ -150,11 +153,12 @@ export function FilterDialog<T extends Record<string, unknown>>({
150
153
  onClose,
151
154
  ...props
152
155
  }: FilterDialogProps<T>): React.JSX.Element {
156
+ const copy = useDataViewsCopy();
153
157
  return (
154
158
  <StackedModal
155
159
  open={open}
156
160
  onClose={onClose}
157
- navigationTitle="Filtros"
161
+ navigationTitle={copy.filters.panelTitle}
158
162
  modalId={`${props.testIdPrefix}-filters`}
159
163
  maxWidth="xs"
160
164
  dataTestId={`${props.testIdPrefix}-filter-dialog`}
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
 
3
+ import { useDataViewsCopy } from "./data-views-copy-context";
3
4
  import { type GridColumn } from "../DataGrid";
4
5
  import { type SortFieldDefinition } from "../../layout/ContentToolbar";
5
6
  import { Box } from "../../../mui/Box";
@@ -105,6 +106,7 @@ function renderAutoKebab<T extends Record<string, unknown>>(
105
106
  testIdPrefix: string,
106
107
  getRowId: (row: T) => string | number,
107
108
  ): React.ReactNode {
109
+ const copy = useDataViewsCopy();
108
110
  const items: DropdownMenuItem[] = kebabActions
109
111
  .filter((action) => action.isVisible?.(row) ?? true)
110
112
  .map((action) => ({
@@ -119,7 +121,7 @@ function renderAutoKebab<T extends Record<string, unknown>>(
119
121
  size="sm"
120
122
  items={items}
121
123
  trigger={
122
- <Button variant="text" size="sm" dataTestId={`${testIdPrefix}-actions-${getRowId(row)}`} aria-label="Ações">
124
+ <Button variant="text" size="sm" dataTestId={`${testIdPrefix}-actions-${getRowId(row)}`} aria-label={copy.grid.rowActions}>
123
125
  ⋮
124
126
  </Button>
125
127
  }
@@ -222,6 +224,7 @@ export function renderBulkActions<T extends Record<string, unknown>>({
222
224
  clearSelection,
223
225
  testIdPrefix,
224
226
  }: RenderBulkArgs<T>): React.ReactNode {
227
+ const copy = useDataViewsCopy();
225
228
  if (selectedRows.length === 0) return undefined;
226
229
  if (rowActions) {
227
230
  const items = bulkMenuItems(rowActions, selectedRows, clearSelection);
@@ -232,7 +235,7 @@ export function renderBulkActions<T extends Record<string, unknown>>({
232
235
  items={items}
233
236
  trigger={
234
237
  <Button variant="outline" size="sm" dataTestId={`${testIdPrefix}-bulk-actions`}>
235
- Ações ({selectedRows.length}) ▾
238
+ {copy.grid.bulkActions(selectedRows.length)}
236
239
  </Button>
237
240
  }
238
241
  />
@@ -22,6 +22,7 @@ import type { OverflowField } from "./data-views-overflow";
22
22
  import { RangeBounds } from "./data-views-range-pill";
23
23
  import { isRangeSet } from "./data-views-range-values";
24
24
  import type { RangeValue } from "./data-views-types";
25
+ import { useDataViewsCopy } from "./data-views-copy-context";
25
26
 
26
27
  /** What each field's control needs, minus the panel's own chrome. */
27
28
  export interface MoreFieldProps {
@@ -54,6 +55,7 @@ function OverflowPill<T extends Record<string, unknown>>({
54
55
  onClear: () => void;
55
56
  testIdPrefix: string;
56
57
  }): React.JSX.Element {
58
+ const copy = useDataViewsCopy();
57
59
  const options = field.pill?.options ?? [];
58
60
  if (options.length > INLINE_OPTION_LIMIT) {
59
61
  return (
@@ -63,10 +65,10 @@ function OverflowPill<T extends Record<string, unknown>>({
63
65
  selected={new Set(values)}
64
66
  onToggle={onToggle}
65
67
  onClear={onClear}
66
- allLabel="Todas"
68
+ allLabel={copy.filters.allOption}
67
69
  searchable={options.length > 6 ? true : undefined}
68
- searchPlaceholder="Buscar…"
69
- noResultsLabel="Nenhum resultado"
70
+ searchPlaceholder={copy.filters.optionSearchPlaceholder}
71
+ noResultsLabel={copy.filters.optionsEmpty}
70
72
  layout="pill"
71
73
  data-testid={`${testIdPrefix}-more-${field.id}`}
72
74
  />
@@ -10,6 +10,7 @@ import FilterAltRoundedIcon from "@mui/icons-material/FilterAltRounded";
10
10
  import { Popover } from "@mui/material";
11
11
  import { useState } from "react";
12
12
 
13
+ import { useDataViewsCopy } from "./data-views-copy-context";
13
14
  import { Button } from "../../form/Button";
14
15
  import { Box } from "../../../mui/Box";
15
16
  import { Text } from "../../typography/Text";
@@ -58,6 +59,7 @@ function MoreTrigger({
58
59
  onOpen: (anchor: HTMLElement) => void;
59
60
  testIdPrefix: string;
60
61
  }): React.JSX.Element {
62
+ const copy = useDataViewsCopy();
61
63
  const applied = appliedCount > 0;
62
64
  return (
63
65
  <Button
@@ -68,8 +70,8 @@ function MoreTrigger({
68
70
  dataTestId={`${testIdPrefix}-more-filters`}
69
71
  aria-label={
70
72
  applied
71
- ? `Mais filtros: ${count} sem espaço na barra, ${appliedCount} aplicado(s)`
72
- : `Mais filtros: ${count} sem espaço na barra`
73
+ ? copy.filters.moreFiltersApplied(count, appliedCount)
74
+ : copy.filters.moreFilters(count)
73
75
  }
74
76
  >
75
77
  <Box
@@ -109,6 +111,7 @@ function MoreTrigger({
109
111
 
110
112
  /** The panel's heading: what these are, and why they are in here. */
111
113
  function MoreHeading(): React.JSX.Element {
114
+ const copy = useDataViewsCopy();
112
115
  return (
113
116
  <Box
114
117
  sx={{
@@ -128,7 +131,7 @@ function MoreHeading(): React.JSX.Element {
128
131
  </Text>
129
132
  <Text variant="caption" as="span">
130
133
  <Box component="span" sx={{ ml: "auto", color: "text.disabled" }}>
131
- sem espaço na barra
134
+ {copy.filters.overflowNote}
132
135
  </Box>
133
136
  </Text>
134
137
  </Box>
@@ -16,6 +16,7 @@ import ChevronDownIcon from '@mui/icons-material/KeyboardArrowDown';
16
16
  import { Box, Button, Popover, Typography } from '@mui/material';
17
17
  import React, { useState } from 'react';
18
18
 
19
+ import { useDataViewsCopy } from "./data-views-copy-context";
19
20
  import { TableFilter } from '../../layout/TableFilter';
20
21
  import { DayBoundInput } from './data-views-day-input';
21
22
  import { NumberBoundInput } from './data-views-number-input';
@@ -89,13 +90,14 @@ export function RangeBounds<T extends Record<string, unknown>>({
89
90
  onChange: (range: RangeValue) => void;
90
91
  testId: string;
91
92
  }): React.JSX.Element {
93
+ const copy = useDataViewsCopy();
92
94
  const inverted = isRangeInverted(value);
93
95
  return (
94
96
  <Box data-testid={`${testId}-panel`}>
95
97
  {/* Above the inputs, not below: the presets are the answer for most
96
98
  merchants, and the two date pickers are the escape hatch. */}
97
99
  <Box sx={{ '&:not(:empty)': { mb: 1.5 } }}>
98
- <RangePresets presets={presetsFor(field)} value={value} onChange={onChange} testId={testId} />
100
+ <RangePresets presets={presetsFor(field, copy)} value={value} onChange={onChange} testId={testId} />
99
101
  </Box>
100
102
  <Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5 }}>
101
103
  <BoundField
@@ -107,7 +109,7 @@ export function RangeBounds<T extends Record<string, unknown>>({
107
109
  />
108
110
  <BoundField
109
111
  field={field}
110
- label="Até"
112
+ label={copy.filters.rangeEnd}
111
113
  value={value.max}
112
114
  onChange={(max) => onChange({ ...value, max })}
113
115
  testId={`${testId}-max`}
@@ -119,7 +121,7 @@ export function RangeBounds<T extends Record<string, unknown>>({
119
121
  data-testid={`${testId}-inverted`}
120
122
  sx={{ mt: 0.75, fontSize: '0.75rem', color: 'error.main' }}
121
123
  >
122
- O início precisa ser menor que o fim.
124
+ {copy.filters.rangeInvalid}
123
125
  </Typography>
124
126
  )}
125
127
  {/* BOTH days are in the result. Saying so is FUT-668's other half: the
@@ -153,6 +155,7 @@ function ClearAffordance({
153
155
  onClear: () => void;
154
156
  testId: string;
155
157
  }): React.JSX.Element {
158
+ const copy = useDataViewsCopy();
156
159
  const clear = (event: React.SyntheticEvent): void => {
157
160
  event.stopPropagation();
158
161
  onClear();
@@ -162,7 +165,7 @@ function ClearAffordance({
162
165
  component="span"
163
166
  role="button"
164
167
  tabIndex={0}
165
- aria-label={`Limpar ${label}`}
168
+ aria-label={copy.filters.clearRange(label)}
166
169
  data-testid={testId}
167
170
  onClick={clear}
168
171
  onKeyDown={(event: React.KeyboardEvent) => {
@@ -326,6 +329,7 @@ export function PanelRangeField<T extends Record<string, unknown>>({
326
329
  onChange: (range: RangeValue) => void;
327
330
  testId: string;
328
331
  }): React.JSX.Element {
332
+ const copy = useDataViewsCopy();
329
333
  if (field.kind === "day") {
330
334
  return (
331
335
  <Box sx={{ display: "flex", flexDirection: "column", gap: 1 }}>
@@ -348,7 +352,7 @@ export function PanelRangeField<T extends Record<string, unknown>>({
348
352
  {/* Below the numeric control here, unlike the pill's popover: this one
349
353
  renders its own label, and chips above it would separate the label
350
354
  from the field it names. */}
351
- <RangePresets presets={presetsFor(field)} value={value} onChange={onChange} testId={testId} />
355
+ <RangePresets presets={presetsFor(field, copy)} value={value} onChange={onChange} testId={testId} />
352
356
  </Box>
353
357
  );
354
358
  }
@@ -1,3 +1,4 @@
1
+ import type { DataViewsCopy } from "./data-views-copy";
1
2
  import type { RangeFieldConfig, RangePreset, RangeValue } from "./data-views-types";
2
3
 
3
4
  /**
@@ -41,10 +42,10 @@ function shiftDays(date: Date, days: number): Date {
41
42
  * The week starts on SUNDAY, following the Brazilian calendar these grids are
42
43
  * read against rather than ISO-8601's Monday.
43
44
  */
44
- export const DAY_RANGE_PRESETS: RangePreset[] = [
45
+ export function dayRangePresets(copy: DataViewsCopy): RangePreset[] {
46
+ return [
45
47
  {
46
48
  id: "hoje",
47
- label: "Hoje",
48
49
  range: () => {
49
50
  const today = isoDay(new Date());
50
51
  return { min: today, max: today };
@@ -52,7 +53,6 @@ export const DAY_RANGE_PRESETS: RangePreset[] = [
52
53
  },
53
54
  {
54
55
  id: "ontem",
55
- label: "Ontem",
56
56
  range: () => {
57
57
  const yesterday = isoDay(shiftDays(new Date(), -1));
58
58
  return { min: yesterday, max: yesterday };
@@ -60,7 +60,6 @@ export const DAY_RANGE_PRESETS: RangePreset[] = [
60
60
  },
61
61
  {
62
62
  id: "semana",
63
- label: "Esta semana",
64
63
  range: () => {
65
64
  const now = new Date();
66
65
  const sunday = shiftDays(now, -now.getDay());
@@ -69,7 +68,6 @@ export const DAY_RANGE_PRESETS: RangePreset[] = [
69
68
  },
70
69
  {
71
70
  id: "mes",
72
- label: "Este mês",
73
71
  range: () => {
74
72
  const now = new Date();
75
73
  const year = now.getFullYear();
@@ -81,13 +79,13 @@ export const DAY_RANGE_PRESETS: RangePreset[] = [
81
79
  },
82
80
  {
83
81
  id: "ano",
84
- label: "Este ano",
85
82
  range: () => {
86
83
  const year = new Date().getFullYear();
87
84
  return { min: `${year}-01-01`, max: `${year}-12-31` };
88
85
  },
89
86
  },
90
- ];
87
+ ].map((preset) => ({ ...preset, label: copy.filters.rangePresets[preset.id] ?? preset.id }));
88
+ }
91
89
 
92
90
  /**
93
91
  * The presets a field offers: its own, or the calendar defaults for a day field
@@ -96,9 +94,10 @@ export const DAY_RANGE_PRESETS: RangePreset[] = [
96
94
  */
97
95
  export function presetsFor<T extends Record<string, unknown>>(
98
96
  field: RangeFieldConfig<T>,
97
+ copy: DataViewsCopy,
99
98
  ): RangePreset[] {
100
99
  if (field.presets) return field.presets;
101
- return field.kind === "day" ? DAY_RANGE_PRESETS : [];
100
+ return field.kind === "day" ? dayRangePresets(copy) : [];
102
101
  }
103
102
 
104
103
  /** A preset's window, evaluating it if it is time-dependent. */
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { useEffect, useMemo, useRef } from "react";
4
4
 
5
+ import { useDataViewsCopy } from "./data-views-copy-context";
5
6
  import { Box } from "../../../mui/Box";
6
7
 
7
8
  /**
@@ -320,6 +321,7 @@ export function DataViewsScopeTabs({
320
321
  counts,
321
322
  testIdPrefix,
322
323
  }: DataViewsScopeTabsProps): React.JSX.Element | null {
324
+ const copy = useDataViewsCopy();
323
325
  const stripRef = useScrollActiveIntoView(value);
324
326
  const moveTo = (index: number): void => {
325
327
  // Focus FIRST, then select: the roving tabindex follows the selection, so
@@ -337,7 +339,7 @@ export function DataViewsScopeTabs({
337
339
  );
338
340
 
339
341
  return (
340
- <Box ref={stripRef} role="tablist" aria-label="Situação" data-testid={`${testIdPrefix}-scopes`} sx={STRIP_SX}>
342
+ <Box ref={stripRef} role="tablist" aria-label={copy.filters.scopesLabel} data-testid={`${testIdPrefix}-scopes`} sx={STRIP_SX}>
341
343
  {scopes.map((scope, index) => (
342
344
  <ScopeTab
343
345
  key={scope.id}
@@ -11,6 +11,7 @@ import { IconButton, InputAdornment, TextField } from "@mui/material";
11
11
  import { useEffect, useRef, useState } from "react";
12
12
 
13
13
  import { Box } from "../../../mui/Box";
14
+ import { useDataViewsCopy } from "./data-views-copy-context";
14
15
 
15
16
  /** How long the box waits after the last keystroke before it queries. */
16
17
  const SEARCH_DEBOUNCE_MS = 350;
@@ -60,6 +61,7 @@ export function InlineKeyword({
60
61
  /** Take whatever width there is, with no minimum — see {@link boxWidth}. */
61
62
  fill?: boolean;
62
63
  }): React.JSX.Element {
64
+ const copy = useDataViewsCopy();
63
65
  const [draft, setDraft] = useState(value);
64
66
  const prev = useRef(value);
65
67
  // An external change (a saved view, the URL, "Limpar") wins over the draft.
@@ -92,8 +94,8 @@ export function InlineKeyword({
92
94
  event.preventDefault();
93
95
  if (draft !== value) onChange(draft);
94
96
  }}
95
- placeholder="Buscar…"
96
- inputProps={{ "aria-label": "Buscar em todas as colunas", "data-testid": testId }}
97
+ placeholder={copy.search.placeholder}
98
+ inputProps={{ "aria-label": copy.search.allColumnsLabel, "data-testid": testId }}
97
99
  InputProps={{
98
100
  startAdornment: (
99
101
  <InputAdornment position="start">
@@ -104,7 +106,7 @@ export function InlineKeyword({
104
106
  <InputAdornment position="end">
105
107
  <IconButton
106
108
  size="small"
107
- aria-label="Limpar busca"
109
+ aria-label={copy.search.clear}
108
110
  data-testid={testId ? `${testId}-clear` : undefined}
109
111
  onClick={() => setDraft("")}
110
112
  sx={{ p: 0.25 }}
@@ -137,11 +139,12 @@ export function CollapsedSearch({
137
139
  onOpen: () => void;
138
140
  testId?: string;
139
141
  }): React.JSX.Element {
142
+ const copy = useDataViewsCopy();
140
143
  return (
141
144
  <IconButton
142
145
  size="small"
143
146
  onClick={onOpen}
144
- aria-label="Buscar"
147
+ aria-label={copy.search.open}
145
148
  aria-expanded={false}
146
149
  data-testid={testId ? `${testId}-collapsed` : undefined}
147
150
  sx={{
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { Checkbox } from "@mui/material";
4
4
 
5
+ import { useDataViewsCopy } from "./data-views-copy-context";
5
6
  import { Button } from "../../form/Button";
6
7
  import { Box } from "../../../mui/Box";
7
8
  import { Text } from "../../typography/Text";
@@ -38,6 +39,7 @@ export function SelectAllStrip<T>({
38
39
  onChange: (next: Set<string | number>) => void;
39
40
  testIdPrefix: string;
40
41
  }): React.JSX.Element | null {
42
+ const copy = useDataViewsCopy();
41
43
  if (rows.length === 0) return null;
42
44
  const pageIds = rows.map(getRowId);
43
45
  const selectedHere = pageIds.filter((id) => selectedIds.has(id)).length;
@@ -81,7 +83,7 @@ export function SelectAllStrip<T>({
81
83
  indeterminate={some}
82
84
  onChange={toggle}
83
85
  data-testid={`${testIdPrefix}-select-all-box`}
84
- inputProps={{ "aria-label": "Selecionar todos nesta página" }}
86
+ inputProps={{ "aria-label": copy.selection.selectAllOnPage }}
85
87
  sx={{ p: 0.5 }}
86
88
  />
87
89
  <Button
@@ -91,13 +93,13 @@ export function SelectAllStrip<T>({
91
93
  onClick={toggle}
92
94
  dataTestId={`${testIdPrefix}-select-all-toggle`}
93
95
  >
94
- {all ? "Limpar seleção" : "Selecionar tudo"}
96
+ {all ? copy.selection.clearSelection : copy.selection.selectAll}
95
97
  </Button>
96
98
  <Text variant="caption" as="span">
97
99
  {/* "nesta página" is load-bearing: the scope tabs above show
98
100
  whole-query totals, so an unqualified count here would read as one. */}
99
101
  <Box component="span" sx={{ ml: "auto", color: "text.disabled", whiteSpace: "nowrap" }}>
100
- {rows.length} nesta página
102
+ {copy.selection.onThisPage(rows.length)}
101
103
  </Box>
102
104
  </Text>
103
105
  </Box>
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
 
3
+ import { useDataViewsCopy } from "./data-views-copy-context";
3
4
  import { Alert } from "../Alert";
4
5
  import { SavedViewsMenu } from "../../layout/ContentToolbar";
5
6
 
@@ -25,13 +26,14 @@ export function ViewMutationErrorAlert({
25
26
  onClose: () => void;
26
27
  testIdPrefix: string;
27
28
  }): React.JSX.Element | null {
29
+ const copy = useDataViewsCopy();
28
30
  if (!error) {
29
31
  return null;
30
32
  }
31
33
  return (
32
34
  <Alert
33
35
  variant="danger"
34
- title="Não foi possível atualizar a visão"
36
+ title={copy.nav.updateFailed}
35
37
  description={error}
36
38
  closable
37
39
  onClose={onClose}
@@ -75,8 +77,10 @@ export function ViewsMenuSlot({
75
77
  onManageAll,
76
78
  testIdPrefix,
77
79
  }: ViewsMenuSlotProps): React.JSX.Element {
80
+ const copy = useDataViewsCopy();
78
81
  return (
79
82
  <SavedViewsMenu<SavedViewSummary>
83
+ labels={copy.savedViewsMenu}
80
84
  views={views}
81
85
  activeViewName={activeViewName}
82
86
  onApply={applyView}
@@ -125,6 +129,7 @@ export function ViewDialogs<T extends Record<string, unknown>>({
125
129
  onDelete,
126
130
  testIdPrefix,
127
131
  }: ViewDialogsProps<T>): React.JSX.Element {
132
+ const copy = useDataViewsCopy();
128
133
  return (
129
134
  <>
130
135
  {/* Keyed by the view being edited: the form seeds its fields with
@@ -142,7 +147,7 @@ export function ViewDialogs<T extends Record<string, unknown>>({
142
147
  onSave={onSave}
143
148
  testIdPrefix={`${testIdPrefix}-views`}
144
149
  />
145
- <ManageViewsDialog
150
+ <ManageViewsDialog confirmCopy={copy.confirmAction}
146
151
  open={manageOpen}
147
152
  onClose={onCloseManage}
148
153
  views={views}
@@ -7,7 +7,7 @@
7
7
  * Two levels, both of them replacing the panel's BODY (the tabs stay put):
8
8
  * the list of views, and one view's actions. It is a drill-down and not a
9
9
  * nested menu on purpose — an absolutely positioned popover inside the panel's
10
- * own scroll container gets clipped by it, which is how "Excluir visão" ends
10
+ * own scroll container gets clipped by it, which is how copy.nav.deleteView ends
11
11
  * up unreachable. One level, no clipping, and it works on touch.
12
12
  */
13
13
  import ChevronLeftRoundedIcon from "@mui/icons-material/ChevronLeftRounded";
@@ -25,6 +25,7 @@ import KeyboardArrowDownRoundedIcon from "@mui/icons-material/KeyboardArrowDownR
25
25
  import RestartAltRoundedIcon from "@mui/icons-material/RestartAltRounded";
26
26
  import SaveOutlinedIcon from "@mui/icons-material/SaveOutlined";
27
27
 
28
+ import { useDataViewsCopy } from "./data-views-copy-context";
28
29
  import { Button } from "../../form/Button";
29
30
  import { Box } from "../../../mui/Box";
30
31
  import { Text } from "../../typography/Text";
@@ -36,7 +37,7 @@ import type { SavedViewSummary } from "./data-views-types";
36
37
  export interface ViewNavHandlers {
37
38
  views: SavedViewSummary[];
38
39
  activeViewId?: string | null;
39
- /** `null` selects the built-in "Visão principal". */
40
+ /** `null` selects the built-in "{copy.nav.mainView}". */
40
41
  onSelectView: (id: string | null) => void;
41
42
  onEditView: (view: SavedViewSummary) => void;
42
43
  onPatchView: (
@@ -74,6 +75,7 @@ export function ViewsList({
74
75
  onOpenActions: (view: SavedViewSummary) => void;
75
76
  testIdPrefix: string;
76
77
  }): React.JSX.Element {
78
+ const copy = useDataViewsCopy();
77
79
  const { views, activeViewId, onSelectView } = handlers;
78
80
  const onMain = !activeViewId;
79
81
  return (
@@ -86,7 +88,7 @@ export function ViewsList({
86
88
  sx={{ ...rowSx, color: onMain ? "primary.main" : "text.primary", fontWeight: onMain ? 600 : 400 }}
87
89
  >
88
90
  <Box component="span" sx={{ flex: 1 }}>
89
- Visão principal
91
+ {copy.nav.mainView}
90
92
  </Box>
91
93
  {onMain && <CheckRoundedIcon fontSize="small" />}
92
94
  </Box>
@@ -108,7 +110,7 @@ export function ViewsList({
108
110
  {/* What the row-menu toggles DID, readable without opening it:
109
111
  a view set as default, pinned or shared says so here. */}
110
112
  {view.isDefault && (
111
- <StarOutlineRoundedIcon fontSize="small" sx={{ color: "warning.main" }} titleAccess="Padrão" />
113
+ <StarOutlineRoundedIcon fontSize="small" sx={{ color: "warning.main" }} titleAccess={copy.nav.defaultTag} />
112
114
  )}
113
115
  {view.pinned && (
114
116
  <PushPinOutlinedIcon fontSize="small" sx={{ color: "text.disabled" }} titleAccess="Fixada" />
@@ -121,7 +123,7 @@ export function ViewsList({
121
123
  <IconButton
122
124
  size="small"
123
125
  onClick={() => onOpenActions(view)}
124
- aria-label={`Opções de ${view.name}`}
126
+ aria-label={copy.nav.viewOptions(view.name)}
125
127
  data-testid={`${testIdPrefix}-view-${view.id}-menu`}
126
128
  >
127
129
  <MoreVertRoundedIcon fontSize="small" />
@@ -133,7 +135,7 @@ export function ViewsList({
133
135
  {views.length === 0 && (
134
136
  <Text variant="caption" as="p">
135
137
  <Box component="span" sx={{ display: "block", px: 1.25, py: 1.5, color: "text.secondary", lineHeight: 1.6 }}>
136
- Nenhuma visão salva. Ajuste filtros, colunas ou ordenação e salve abaixo.
138
+ {copy.nav.emptyHint}
137
139
  </Box>
138
140
  </Text>
139
141
  )}
@@ -153,6 +155,7 @@ export function ViewActions({
153
155
  onBack: () => void;
154
156
  testIdPrefix: string;
155
157
  }): React.JSX.Element {
158
+ const copy = useDataViewsCopy();
156
159
  const { onEditView, onPatchView, onDeleteView } = handlers;
157
160
  const action = (
158
161
  key: string,
@@ -195,12 +198,12 @@ export function ViewActions({
195
198
  </Box>
196
199
  </Box>
197
200
  <Box sx={{ my: 0.5, borderTop: 1, borderColor: "divider" }} />
198
- {action("edit", EditOutlinedIcon, "Renomear e editar", () => onEditView(view))}
199
- {action("default", StarOutlineRoundedIcon2, "Definir como padrão", () => onPatchView(view, { isDefault: !view.isDefault }), { on: view.isDefault })}
200
- {action("pin", PushPinOutlinedIcon, "Fixar na barra lateral", () => onPatchView(view, { pinned: !view.pinned }), { on: view.pinned })}
201
- {action("share", GroupOutlinedIcon, "Compartilhar com a equipe", () => onPatchView(view, { shared: !view.shared }), { on: view.shared })}
201
+ {action("edit", EditOutlinedIcon, copy.nav.editView, () => onEditView(view))}
202
+ {action("default", StarOutlineRoundedIcon2, copy.nav.setDefault, () => onPatchView(view, { isDefault: !view.isDefault }), { on: view.isDefault })}
203
+ {action("pin", PushPinOutlinedIcon, copy.nav.pinToSidebar, () => onPatchView(view, { pinned: !view.pinned }), { on: view.pinned })}
204
+ {action("share", GroupOutlinedIcon, copy.nav.shareWithTeam, () => onPatchView(view, { shared: !view.shared }), { on: view.shared })}
202
205
  <Box sx={{ my: 0.5, borderTop: 1, borderColor: "divider" }} />
203
- {action("delete", DeleteOutlineRoundedIcon, "Excluir visão", () => onDeleteView(view), { danger: true })}
206
+ {action("delete", DeleteOutlineRoundedIcon, copy.nav.deleteView, () => onDeleteView(view), { danger: true })}
204
207
  </Box>
205
208
  );
206
209
  }
@@ -217,15 +220,16 @@ function ToggleContents({
217
220
  interactive: boolean;
218
221
  testIdPrefix: string;
219
222
  }): React.JSX.Element {
223
+ const copy = useDataViewsCopy();
220
224
  return (
221
225
  <>
222
226
  <Box component="span" sx={{ fontWeight: 600 }} data-testid={`${testIdPrefix}-display-view-name`}>
223
- {view.activeViewName ?? "Visão principal"}
227
+ {view.activeViewName ?? "{copy.nav.mainView}"}
224
228
  </Box>
225
229
  {view.dirty && (
226
230
  <Box
227
231
  component="span"
228
- aria-label="Alterações não salvas"
232
+ aria-label={copy.nav.unsavedChanges}
229
233
  data-testid={`${testIdPrefix}-display-dirty`}
230
234
  sx={{ height: 6, width: 6, borderRadius: "50%", bgcolor: "primary.main" }}
231
235
  />
@@ -291,11 +295,12 @@ export function ViewHeader(props: {
291
295
  onToggle: () => void;
292
296
  testIdPrefix: string;
293
297
  }): React.JSX.Element {
298
+ const copy = useDataViewsCopy();
294
299
  return (
295
300
  <Box sx={{ display: "flex", alignItems: "center", gap: 1, px: 1.5, py: 1, borderBottom: 1, borderColor: "divider" }}>
296
301
  <Text variant="caption" as="span">
297
302
  <Box component="span" sx={{ textTransform: "uppercase", letterSpacing: 0.5, color: "text.disabled" }}>
298
- Visão
303
+ {copy.nav.label}
299
304
  </Box>
300
305
  </Text>
301
306
  <ViewToggle {...props} />
@@ -313,6 +318,7 @@ export function ViewFooter({
313
318
  onDone: () => void;
314
319
  testIdPrefix: string;
315
320
  }): React.JSX.Element {
321
+ const copy = useDataViewsCopy();
316
322
  return (
317
323
  <Box
318
324
  sx={{
@@ -339,7 +345,7 @@ export function ViewFooter({
339
345
  Redefinir
340
346
  </Button>
341
347
  <Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
342
- {/* Only meaningful with a view APPLIED: on Visão principal the single
348
+ {/* Only meaningful with a view APPLIED: on {copy.nav.mainView} the single
343
349
  "Salvar visão" already is "save as new". */}
344
350
  {view.onUpdate && (
345
351
  <Button
@@ -369,7 +375,7 @@ export function ViewFooter({
369
375
  }}
370
376
  dataTestId={`${testIdPrefix}-display-save`}
371
377
  >
372
- {view.onUpdate ? "Atualizar visão" : "Salvar visão"}
378
+ {view.onUpdate ? copy.nav.update : copy.nav.save}
373
379
  </Button>
374
380
  </Box>
375
381
  </Box>
@@ -74,3 +74,23 @@ export type {
74
74
  DataViewQuery,
75
75
  DataViewServer,
76
76
  } from "./data-views-types";
77
+
78
+ // The words this surface renders, and the provider that puts them in scope.
79
+ // REQUIRED config: `useDataViewsCopy` throws outside a provider rather than
80
+ // falling back to the origin host's Portuguese (FUT-760).
81
+ export { DataViewsCopyProvider, useDataViewsCopy } from "./data-views-copy-context";
82
+ export type {
83
+ DataViewsCopy,
84
+ DataViewsBoardCopy,
85
+ DeleteViewCopy,
86
+ ManageViewsCopy,
87
+ SaveViewCopy,
88
+ DataViewsColumnsCopy,
89
+ DataViewsDisplayCopy,
90
+ DataViewsExportCopy,
91
+ DataViewsGridCopy,
92
+ DataViewsFiltersCopy,
93
+ DataViewsSelectionCopy,
94
+ DataViewsNavCopy,
95
+ DataViewsSearchCopy,
96
+ } from "./data-views-copy";