@rojaostudio/ds 2.0.0-next.20 → 2.0.0-next.21

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.
@@ -35,6 +35,12 @@ type DataTableHeaderProps = {
35
35
  * Checkbox "Agrupar por produto". In view in the compact arrangement too.
36
36
  */
37
37
  view?: ReactNode;
38
+ /**
39
+ * The list's action (Figma: `showActions`, off by default, + the `actions` instance): an IconButton, neutral outline
40
+ * md, with its Tooltip, such as a gear "Organizar categorias" or exporting. It sits outside the tools, always at the
41
+ * end of the FIRST line, on the right; the tools wrap, the action never goes down.
42
+ * Creating is NOT an action of the bar: creating is the FAB. The component does not enforce this; it documents it.
43
+ */
38
44
  actions?: ReactNode;
39
45
  className?: string;
40
46
  /** In the compact arrangement (bar below 1024), moves the filters and the actions into a Drawer. The quick filters stay in view. */
@@ -47,8 +53,10 @@ declare function FilterDropdown({ f, placement }: {
47
53
  }): react.JSX.Element;
48
54
  /**
49
55
  * DataTableHeader — a composition of the Input (search), FilterChips, Buttons, the DropdownMenu, the Popover and
50
- * the Drawer: the bar above a table. The search is always on the left and takes the free width (at least 320); the
51
- * filters are always on the right; what does not fit wraps. Quick filters go in the `quickFilters` slot; one filter
56
+ * the Drawer: the bar above a table. A row that never wraps: the tools (the search, the quick filters, the filters,
57
+ * the view control) wrap inside their own group; the action stays outside it, at the end of the first line, on the
58
+ * right. The search is always on the left and takes the free width (at least 320); the filters are always on the
59
+ * right; what does not fit wraps. Quick filters go in the `quickFilters` slot; one filter
52
60
  * is a dropdown, two or more collapse into "Filtros" (the active ones stay in view as removable Chips); the `view`
53
61
  * control comes after the filters, before the actions. "Filtros · N" counts the active `filters`, the ones that
54
62
  * button opens.
@@ -155,85 +155,87 @@ function DataTableHeader({
155
155
  const singleFilter = filters.length === 1 ? filters[0] : null;
156
156
  const lead = Boolean(search || quickFilters);
157
157
  return /* @__PURE__ */ jsxs("div", { className: ["rds-data-table-header", className].filter(Boolean).join(" "), children: [
158
- search && /* @__PURE__ */ jsx(
159
- Input,
160
- {
161
- className: "rds-data-table-header__search",
162
- type: "search",
163
- "aria-label": (_a = search.placeholder) != null ? _a : "Buscar\u2026",
164
- placeholder: (_b = search.placeholder) != null ? _b : "Buscar\u2026",
165
- leadingIcon: /* @__PURE__ */ jsx(SearchIcon, {}),
166
- clearable: true,
167
- clearLabel: "Limpar busca",
168
- value: search.value,
169
- onChange: (e) => search.onChange(e.target.value)
170
- }
171
- ),
172
- quickFilters && /* @__PURE__ */ jsx("div", { className: "rds-data-table-header__quick", children: quickFilters }),
173
- filters.length > 0 && /* @__PURE__ */ jsxs("div", { className: "rds-data-table-header__wide", children: [
174
- lead && /* @__PURE__ */ jsx(Separator, { orientation: "vertical" }),
175
- collapseDesktop ? /* @__PURE__ */ jsxs(Fragment, { children: [
176
- activeFilters.map((f) => /* @__PURE__ */ jsx(Chip, { onRemove: () => f.onChange(""), removeLabel: `Remover filtro ${f.label}`, children: optionLabel(f) }, f.key)),
177
- /* @__PURE__ */ jsx(
178
- FiltersPopover,
179
- {
180
- filters,
181
- onClear,
182
- showClear: activeFilterCount > 0,
183
- trigger: /* @__PURE__ */ jsx(FiltersButton, { count: activeFilterCount })
184
- }
185
- )
186
- ] }) : filters.map((f) => /* @__PURE__ */ jsx(FilterDropdown, { f }, f.key)),
187
- onClear && activeFilterCount > 0 && !collapseDesktop && /* @__PURE__ */ jsx(Tooltip, { text: "Limpar filtros", children: /* @__PURE__ */ jsx(IconButton, { icon: /* @__PURE__ */ jsx(CloseIcon, {}), label: "Limpar filtros", variant: "ghost", tone: "neutral", onClick: onClear }) })
188
- ] }),
189
- singleFilter && !(mobileCollapse && actions) && /* @__PURE__ */ jsx("div", { className: "rds-data-table-header__narrow", children: /* @__PURE__ */ jsx(MobileSingleFilter, { f: singleFilter }) }),
190
- !mobileCollapse && filters.length >= 2 && /* @__PURE__ */ jsx("div", { className: "rds-data-table-header__narrow", children: /* @__PURE__ */ jsx(
191
- FiltersPopover,
192
- {
193
- filters,
194
- onClear,
195
- showClear: activeFilterCount > 0,
196
- trigger: /* @__PURE__ */ jsx(
197
- CompactFilterTrigger,
198
- {
199
- label: "Filtros",
200
- state: activeState(activeFilterCount),
201
- indicator: activeFilterCount > 0 ? activeFilterCount : void 0
202
- }
203
- )
204
- }
205
- ) }),
206
- mobileCollapse && (filters.length >= 2 || actions) && /* @__PURE__ */ jsxs("div", { className: "rds-data-table-header__narrow", children: [
207
- /* @__PURE__ */ jsx(
208
- CompactFilterTrigger,
158
+ /* @__PURE__ */ jsxs("div", { className: "rds-data-table-header__tools", children: [
159
+ search && /* @__PURE__ */ jsx(
160
+ Input,
209
161
  {
210
- label: "Filtros",
211
- state: activeState(activeFilterCount),
212
- indicator: activeFilterCount === 0 ? void 0 : filters.length === 1 ? "dot" : activeFilterCount,
213
- onClick: () => setSheetOpen(true)
162
+ className: "rds-data-table-header__search",
163
+ type: "search",
164
+ "aria-label": (_a = search.placeholder) != null ? _a : "Buscar\u2026",
165
+ placeholder: (_b = search.placeholder) != null ? _b : "Buscar\u2026",
166
+ leadingIcon: /* @__PURE__ */ jsx(SearchIcon, {}),
167
+ clearable: true,
168
+ clearLabel: "Limpar busca",
169
+ value: search.value,
170
+ onChange: (e) => search.onChange(e.target.value)
214
171
  }
215
172
  ),
216
- /* @__PURE__ */ jsx(Drawer, { open: sheetOpen, onOpenChange: setSheetOpen, title: "Filtros", children: /* @__PURE__ */ jsxs("div", { className: "rds-data-table-header__groups", children: [
173
+ quickFilters && /* @__PURE__ */ jsx("div", { className: "rds-data-table-header__quick", children: quickFilters }),
174
+ filters.length > 0 && /* @__PURE__ */ jsxs("div", { className: "rds-data-table-header__wide", children: [
175
+ lead && /* @__PURE__ */ jsx(Separator, { orientation: "vertical" }),
176
+ collapseDesktop ? /* @__PURE__ */ jsxs(Fragment, { children: [
177
+ activeFilters.map((f) => /* @__PURE__ */ jsx(Chip, { onRemove: () => f.onChange(""), removeLabel: `Remover filtro ${f.label}`, children: optionLabel(f) }, f.key)),
178
+ /* @__PURE__ */ jsx(
179
+ FiltersPopover,
180
+ {
181
+ filters,
182
+ onClear,
183
+ showClear: activeFilterCount > 0,
184
+ trigger: /* @__PURE__ */ jsx(FiltersButton, { count: activeFilterCount })
185
+ }
186
+ )
187
+ ] }) : filters.map((f) => /* @__PURE__ */ jsx(FilterDropdown, { f }, f.key)),
188
+ onClear && activeFilterCount > 0 && !collapseDesktop && /* @__PURE__ */ jsx(Tooltip, { text: "Limpar filtros", children: /* @__PURE__ */ jsx(IconButton, { icon: /* @__PURE__ */ jsx(CloseIcon, {}), label: "Limpar filtros", variant: "ghost", tone: "neutral", onClick: onClear }) })
189
+ ] }),
190
+ singleFilter && !(mobileCollapse && actions) && /* @__PURE__ */ jsx("div", { className: "rds-data-table-header__narrow", children: /* @__PURE__ */ jsx(MobileSingleFilter, { f: singleFilter }) }),
191
+ !mobileCollapse && filters.length >= 2 && /* @__PURE__ */ jsx("div", { className: "rds-data-table-header__narrow", children: /* @__PURE__ */ jsx(
192
+ FiltersPopover,
193
+ {
194
+ filters,
195
+ onClear,
196
+ showClear: activeFilterCount > 0,
197
+ trigger: /* @__PURE__ */ jsx(
198
+ CompactFilterTrigger,
199
+ {
200
+ label: "Filtros",
201
+ state: activeState(activeFilterCount),
202
+ indicator: activeFilterCount > 0 ? activeFilterCount : void 0
203
+ }
204
+ )
205
+ }
206
+ ) }),
207
+ mobileCollapse && (filters.length >= 2 || actions) && /* @__PURE__ */ jsxs("div", { className: "rds-data-table-header__narrow", children: [
217
208
  /* @__PURE__ */ jsx(
218
- FilterGroups,
209
+ CompactFilterTrigger,
219
210
  {
220
- filters,
221
- onPick: (f, v) => {
222
- f.onChange(v);
223
- setSheetOpen(false);
224
- },
225
- onClear: onClear ? () => {
226
- onClear();
227
- setSheetOpen(false);
228
- } : void 0,
229
- showClear: activeFilterCount > 0
211
+ label: "Filtros",
212
+ state: activeState(activeFilterCount),
213
+ indicator: activeFilterCount === 0 ? void 0 : filters.length === 1 ? "dot" : activeFilterCount,
214
+ onClick: () => setSheetOpen(true)
230
215
  }
231
216
  ),
232
- actions && /* @__PURE__ */ jsx("div", { className: "rds-data-table-header__drawer-actions", children: actions })
233
- ] }) })
217
+ /* @__PURE__ */ jsx(Drawer, { open: sheetOpen, onOpenChange: setSheetOpen, title: "Filtros", children: /* @__PURE__ */ jsxs("div", { className: "rds-data-table-header__groups", children: [
218
+ /* @__PURE__ */ jsx(
219
+ FilterGroups,
220
+ {
221
+ filters,
222
+ onPick: (f, v) => {
223
+ f.onChange(v);
224
+ setSheetOpen(false);
225
+ },
226
+ onClear: onClear ? () => {
227
+ onClear();
228
+ setSheetOpen(false);
229
+ } : void 0,
230
+ showClear: activeFilterCount > 0
231
+ }
232
+ ),
233
+ actions && /* @__PURE__ */ jsx("div", { className: "rds-data-table-header__drawer-actions", children: actions })
234
+ ] }) })
235
+ ] }),
236
+ view && /* @__PURE__ */ jsx("div", { className: "rds-data-table-header__view", children: view })
234
237
  ] }),
235
- view && /* @__PURE__ */ jsx("div", { className: "rds-data-table-header__view", children: view }),
236
- actions && /* @__PURE__ */ jsx("div", { className: mobileCollapse ? "rds-data-table-header__wide" : "rds-data-table-header__actions", children: actions })
238
+ actions && /* @__PURE__ */ jsx("div", { className: ["rds-data-table-header__actions", mobileCollapse && "rds-data-table-header__wide"].filter(Boolean).join(" "), children: actions })
237
239
  ] });
238
240
  }
239
241
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rojaostudio/ds",
3
- "version": "2.0.0-next.20",
3
+ "version": "2.0.0-next.21",
4
4
  "type": "module",
5
5
  "description": "Rojão Design System — componentes React, estilos e alvo React Native. O motor vive em @rojaostudio/ds-core.",
6
6
  "license": "MIT",
@@ -3583,9 +3583,10 @@ input:focus-visible + .rds-checkbox__box {
3583
3583
  /* @tokens data-table-header */
3584
3584
  /*
3585
3585
  * DataTableHeader: no tokens of its own; the Input, FilterChip, Chip, Button, Separator, Checkbox, DropdownMenu,
3586
- * Popover and Drawer bring theirs. One row, 8 apart, 12 above the table, packed to the right: the search on the left
3587
- * takes the free width, at least 320 (never wider than the bar); the quick filters, the filters, the view control
3588
- * and the actions follow it on the right, and what does not fit wraps.
3586
+ * Popover and Drawer bring theirs. The bar is one row that never wraps, aligned to the top, 8 apart, 12 above the
3587
+ * table: the `tools` group (the search, the quick filters, the filters, the view control) takes the free width and
3588
+ * is what wraps, packed to the right, the search on the left taking the free width, at least 320 (never wider than
3589
+ * the group); the action sits outside it, fixed at the end of the FIRST line, on the right, and never goes down.
3589
3590
  * Two arrangements, by the screen width, as the Figma viewport mode (layout/compact below lg 1024; the SavingBar's cut):
3590
3591
  * expanded from 1024 (the __wide parts: Separator, Buttons with labels); compact below it (the __narrow parts: the
3591
3592
  * filter as an IconButton of 44), where the search accepts 200. On the IconButton, while a filter is on, a dot of 8
@@ -3596,11 +3597,27 @@ input:focus-visible + .rds-checkbox__box {
3596
3597
  box-sizing: border-box;
3597
3598
  width: 100%;
3598
3599
  display: flex;
3600
+ flex-wrap: nowrap;
3601
+ align-items: flex-start;
3602
+ gap: var(--space-8);
3603
+ margin-bottom: var(--space-12);
3604
+ }
3605
+
3606
+ /* Figma `tools`: horizontal, wrap, fill. */
3607
+ .rds-data-table-header__tools {
3608
+ flex: 1 1 0;
3609
+ min-width: 0;
3610
+ display: flex;
3599
3611
  flex-wrap: wrap;
3600
3612
  align-items: center;
3601
3613
  justify-content: flex-end;
3602
3614
  gap: var(--space-8);
3603
- margin-bottom: var(--space-12);
3615
+ }
3616
+
3617
+ /* Figma `actions`: outside `tools`, at the end of the first line. */
3618
+ .rds-data-table-header__actions {
3619
+ flex: none;
3620
+ align-self: flex-start;
3604
3621
  }
3605
3622
 
3606
3623
  /* Scoped to the bar: the field's own `min-width: 0` (internal/field.css) comes later in the bundle. */