@lucasbernardosn/react-table 0.1.0 → 0.2.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.
- package/README.md +269 -0
- package/dist/components/column-menu/column-menu-hide-item.d.ts +3 -3
- package/dist/components/column-menu/column-menu-hide-item.js +1 -2
- package/dist/components/column-menu/column-menu-hide-item.js.map +1 -1
- package/dist/components/column-menu/column-menu-pin-items.d.ts +4 -4
- package/dist/components/column-menu/column-menu-pin-items.js +2 -3
- package/dist/components/column-menu/column-menu-pin-items.js.map +1 -1
- package/dist/components/column-menu/column-menu-popup.d.ts +3 -2
- package/dist/components/column-menu/column-menu-popup.d.ts.map +1 -1
- package/dist/components/column-menu/column-menu-popup.js +10 -9
- package/dist/components/column-menu/column-menu-popup.js.map +1 -1
- package/dist/components/column-menu/column-menu-sort-items.d.ts +5 -4
- package/dist/components/column-menu/column-menu-sort-items.d.ts.map +1 -1
- package/dist/components/column-menu/column-menu-sort-items.js +5 -4
- package/dist/components/column-menu/column-menu-sort-items.js.map +1 -1
- package/dist/components/columns-panel/columns-panel-item.d.ts +5 -2
- package/dist/components/columns-panel/columns-panel-item.d.ts.map +1 -1
- package/dist/components/columns-panel/columns-panel-item.js +45 -28
- package/dist/components/columns-panel/columns-panel-item.js.map +1 -1
- package/dist/components/data-table/body/data-table-body.js +2 -2
- package/dist/components/data-table/body/data-table-body.js.map +1 -1
- package/dist/components/data-table/body/data-table-row.d.ts +3 -3
- package/dist/components/data-table/body/data-table-row.js +11 -7
- package/dist/components/data-table/body/data-table-row.js.map +1 -1
- package/dist/components/data-table/header/data-table-header-row.js +2 -2
- package/dist/components/data-table/header/data-table-header-row.js.map +1 -1
- package/dist/components/data-table/index.parts.d.ts +3 -2
- package/dist/components/data-table/index.parts.js +3 -1
- package/dist/components/data-table/index.parts.js.map +1 -1
- package/dist/components/data-table/resize/data-table-resize-handle.js +1 -0
- package/dist/components/data-table/resize/data-table-resize-handle.js.map +1 -1
- package/dist/components/data-table/root/{data-table-grid-classes.d.ts → data-table-grid-class-names.d.ts} +3 -3
- package/dist/components/data-table/root/data-table-grid-class-names.d.ts.map +1 -0
- package/dist/components/data-table/root/{data-table-grid-classes.js → data-table-grid-class-names.js} +4 -4
- package/dist/components/data-table/root/data-table-grid-class-names.js.map +1 -0
- package/dist/components/data-table/root/data-table-root.js +5 -5
- package/dist/components/data-table/root/data-table-root.js.map +1 -1
- package/dist/components/data-table/root/data-table-scroll-area.d.ts +14 -5
- package/dist/components/data-table/root/data-table-scroll-area.d.ts.map +1 -1
- package/dist/components/data-table/root/data-table-scroll-area.js +17 -7
- package/dist/components/data-table/root/data-table-scroll-area.js.map +1 -1
- package/dist/components/data-table/selection/data-table-selection-bar.d.ts +51 -0
- package/dist/components/data-table/selection/data-table-selection-bar.d.ts.map +1 -0
- package/dist/components/data-table/selection/data-table-selection-bar.js +58 -0
- package/dist/components/data-table/selection/data-table-selection-bar.js.map +1 -0
- package/dist/components/data-table/toolbar/data-table-density-select.d.ts +1 -1
- package/dist/components/data-table/toolbar/data-table-density-select.js +2 -2
- package/dist/components/data-table/toolbar/data-table-density-select.js.map +1 -1
- package/dist/components/data-table/toolbar/data-table-sort-column-select.d.ts +2 -1
- package/dist/components/data-table/toolbar/data-table-sort-column-select.d.ts.map +1 -1
- package/dist/components/data-table/toolbar/data-table-sort-column-select.js +4 -3
- package/dist/components/data-table/toolbar/data-table-sort-column-select.js.map +1 -1
- package/dist/features/row-density/row-density-feature.d.ts +1 -1
- package/dist/features/row-density/row-density-feature.js +1 -1
- package/dist/features/row-density/row-density-feature.js.map +1 -1
- package/dist/features/row-density/row-density-feature.types.d.ts +1 -1
- package/package.json +7 -7
- package/dist/components/data-table/root/data-table-grid-classes.d.ts.map +0 -1
- package/dist/components/data-table/root/data-table-grid-classes.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table-root.js","names":[],"sources":["../../../../src/components/data-table/root/data-table-root.tsx"],"sourcesContent":["import { mergeProps, useRender } from '@base-ui/react';\nimport { mergeTwClassNames } from '@lucasbernardosn/react-ui/utils';\nimport type { MergeOverride } from '@lucasbernardosn/utils';\nimport { useSelector } from '@tanstack/react-store';\nimport type { RowData, TableFeatures } from '@tanstack/react-table';\nimport type { RowDensity } from '../../../features';\nimport type { TableWith } from '../../../types';\nimport { hasTableFeature } from '../../../utils';\nimport { useDataTableLoading } from '../loading/use-data-table-loading';\nimport { useDataTableColumnLayout } from './use-data-table-column-layout';\n\nexport type DataTableRootProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n useRender.ComponentProps<'div'>,\n {\n /** A tabela do `useTable`. Exige `columnSizingFeature`. */\n table: TableWith<TFeatures, TData, 'columnSizingFeature'>;\n }\n>;\n\n/**\n * O elemento do grid (`role=\"table\"`; com `activeRowFeature`, `role=\"grid\"`, que diz ao leitor\n * de tela que as setas são da tabela). Escreve as variáveis das colunas, que toda\n * `DataTable.Row` lê, e tem a largura exata da soma delas.\n *\n * Declara também a altura das linhas e dos headers e o espaçamento das células, que as partes\n * leem. Com `rowDensityFeature`, marca o grid com `data-density`, e esses valores seguem a\n * densidade; para outros valores, redefina as variáveis pela `className`.\n *\n * Com `loadingFeature`, marca `aria-busy` enquanto carrega e, depois de 200ms, `data-loading`: as\n * células trocam o conteúdo por um skeleton, e o `DataTable.ScrollArea` mostra uma barra sob o\n * cabeçalho. Uma resposta mais rápida que isso não mostra nada.\n *\n * Não rola: para rolar, e para o cabeçalho grudar, ponha-o num `DataTable.ScrollArea` ou em\n * outro contêiner com `overflow`.\n *\n * @example\n * ```tsx\n * <DataTable.ScrollArea>\n * <DataTable.Root table={table} aria-label=\"Clientes\">\n * …\n * </DataTable.Root>\n * </DataTable.ScrollArea>\n * ```\n */\nexport const DataTableRoot = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableRootProps<TFeatures, TData>,\n) => {\n const { table, render, className, ref, ...rest } = props;\n\n const rootRef = useDataTableColumnLayout(table);\n\n /**\n * Re-renderiza só o `Root`, e só quando a densidade muda: as linhas chegam prontas por\n * `children`, e as células mudam de tamanho pelas variáveis, sem render.\n */\n const density = useSelector(table.store, (): RowDensity | undefined =>\n hasTableFeature(table, 'rowDensityFeature')\n ? table.atoms.rowDensity.get()\n : undefined,\n );\n\n const loading = useDataTableLoading(table);\n\n const baseProps = {\n 'data-component': 'DataTable.Root',\n 'data-density': density,\n 'data-loading': loading.isLoadingVisible ? '' : undefined,\n // Avisa o leitor de tela que o conteúdo está mudando, e que deve esperar para ler.\n 'aria-busy': loading.isLoading || undefined,\n role: hasTableFeature(table, 'activeRowFeature') ? 'grid' : 'table',\n className: mergeTwClassNames(\n [\n // Largura definida, e não `max-content`: com zoom, o px fracionário faria o conteúdo e\n // as larguras das partes se medirem em ciclo, e o cabeçalho e o corpo parariam em\n // larguras diferentes. Antes do primeiro sync, a variável não existe e vale `auto`.\n 'w-(--data-table-width)',\n\n 'data-[density=compact]:[--data-table-header-height:--spacing(7)]',\n 'data-[density=compact]:[--data-table-row-height:--spacing(8)]',\n 'data-[density=compact]:[--data-table-cell-padding:--spacing(1
|
|
1
|
+
{"version":3,"file":"data-table-root.js","names":[],"sources":["../../../../src/components/data-table/root/data-table-root.tsx"],"sourcesContent":["import { mergeProps, useRender } from '@base-ui/react';\nimport { mergeTwClassNames } from '@lucasbernardosn/react-ui/utils';\nimport type { MergeOverride } from '@lucasbernardosn/utils';\nimport { useSelector } from '@tanstack/react-store';\nimport type { RowData, TableFeatures } from '@tanstack/react-table';\nimport type { RowDensity } from '../../../features';\nimport type { TableWith } from '../../../types';\nimport { hasTableFeature } from '../../../utils';\nimport { useDataTableLoading } from '../loading/use-data-table-loading';\nimport { useDataTableColumnLayout } from './use-data-table-column-layout';\n\nexport type DataTableRootProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n useRender.ComponentProps<'div'>,\n {\n /** A tabela do `useTable`. Exige `columnSizingFeature`. */\n table: TableWith<TFeatures, TData, 'columnSizingFeature'>;\n }\n>;\n\n/**\n * O elemento do grid (`role=\"table\"`; com `activeRowFeature`, `role=\"grid\"`, que diz ao leitor\n * de tela que as setas são da tabela). Escreve as variáveis das colunas, que toda\n * `DataTable.Row` lê, e tem a largura exata da soma delas.\n *\n * Declara também a altura das linhas e dos headers e o espaçamento das células, que as partes\n * leem. Com `rowDensityFeature`, marca o grid com `data-density`, e esses valores seguem a\n * densidade; para outros valores, redefina as variáveis pela `className`.\n *\n * Com `loadingFeature`, marca `aria-busy` enquanto carrega e, depois de 200ms, `data-loading`: as\n * células trocam o conteúdo por um skeleton, e o `DataTable.ScrollArea` mostra uma barra sob o\n * cabeçalho. Uma resposta mais rápida que isso não mostra nada.\n *\n * Não rola: para rolar, e para o cabeçalho grudar, ponha-o num `DataTable.ScrollArea` ou em\n * outro contêiner com `overflow`.\n *\n * @example\n * ```tsx\n * <DataTable.ScrollArea>\n * <DataTable.Root table={table} aria-label=\"Clientes\">\n * …\n * </DataTable.Root>\n * </DataTable.ScrollArea>\n * ```\n */\nexport const DataTableRoot = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableRootProps<TFeatures, TData>,\n) => {\n const { table, render, className, ref, ...rest } = props;\n\n const rootRef = useDataTableColumnLayout(table);\n\n /**\n * Re-renderiza só o `Root`, e só quando a densidade muda: as linhas chegam prontas por\n * `children`, e as células mudam de tamanho pelas variáveis, sem render.\n */\n const density = useSelector(table.store, (): RowDensity | undefined =>\n hasTableFeature(table, 'rowDensityFeature')\n ? table.atoms.rowDensity.get()\n : undefined,\n );\n\n const loading = useDataTableLoading(table);\n\n const baseProps = {\n 'data-component': 'DataTable.Root',\n 'data-density': density,\n 'data-loading': loading.isLoadingVisible ? '' : undefined,\n // Avisa o leitor de tela que o conteúdo está mudando, e que deve esperar para ler.\n 'aria-busy': loading.isLoading || undefined,\n role: hasTableFeature(table, 'activeRowFeature') ? 'grid' : 'table',\n className: mergeTwClassNames(\n [\n // Largura definida, e não `max-content`: com zoom, o px fracionário faria o conteúdo e\n // as larguras das partes se medirem em ciclo, e o cabeçalho e o corpo parariam em\n // larguras diferentes. Antes do primeiro sync, a variável não existe e vale `auto`.\n 'w-(--data-table-width)',\n\n 'data-[density=compact]:[--data-table-header-height:--spacing(7)]',\n 'data-[density=compact]:[--data-table-row-height:--spacing(8)]',\n 'data-[density=compact]:[--data-table-cell-padding:--spacing(1)]',\n\n // Densidade: a padrão vale também sem `rowDensityFeature`.\n '[--data-table-header-height:--spacing(8)]',\n '[--data-table-row-height:--spacing(9)]',\n '[--data-table-cell-padding:--spacing(2)]',\n\n 'data-[density=airy]:[--data-table-header-height:--spacing(9)]',\n 'data-[density=airy]:[--data-table-row-height:--spacing(10)]',\n 'data-[density=airy]:[--data-table-cell-padding:--spacing(3)]',\n ],\n className,\n ),\n };\n\n return useRender({\n render,\n ref: [rootRef, ref ?? null],\n defaultTagName: 'div',\n props: mergeProps(baseProps, rest),\n });\n};\n\nDataTableRoot.displayName = 'DataTable.Root';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CA,MAAa,iBAIX,UACG;CACH,MAAM,EAAE,OAAO,QAAQ,WAAW,KAAK,GAAG,SAAS;CAEnD,MAAM,UAAU,yBAAyB,KAAK;;;;;CAM9C,MAAM,UAAU,YAAY,MAAM,aAChC,gBAAgB,OAAO,mBAAmB,IACtC,MAAM,MAAM,WAAW,IAAI,IAC3B,KAAA,CACN;CAEA,MAAM,UAAU,oBAAoB,KAAK;CAEzC,MAAM,YAAY;EAChB,kBAAkB;EAClB,gBAAgB;EAChB,gBAAgB,QAAQ,mBAAmB,KAAK,KAAA;EAEhD,aAAa,QAAQ,aAAa,KAAA;EAClC,MAAM,gBAAgB,OAAO,kBAAkB,IAAI,SAAS;EAC5D,WAAW,kBACT;GAIE;GAEA;GACA;GACA;GAGA;GACA;GACA;GAEA;GACA;GACA;EACF,GACA,SACF;CACF;CAEA,OAAO,UAAU;EACf;EACA,KAAK,CAAC,SAAS,OAAO,IAAI;EAC1B,gBAAgB;EAChB,OAAO,WAAW,WAAW,IAAI;CACnC,CAAC;AACH;AAEA,cAAc,cAAc"}
|
|
@@ -6,12 +6,21 @@ export type DataTableScrollAreaProps = ScrollArea.RootProps;
|
|
|
6
6
|
* borda, `Viewport`, `Content` e as barras. Os filhos vão no `Content`, e as props no `Root`.
|
|
7
7
|
*
|
|
8
8
|
* O viewport é o ancestral que rola, e é nele que o cabeçalho sticky se ancora. Na largura,
|
|
9
|
-
* abraça o grid e para no pai. Na altura, tem a das linhas: dentro de um pai com altura
|
|
10
|
-
*
|
|
9
|
+
* abraça o grid e para no pai. Na altura, tem a das linhas: dentro de um pai com altura definida
|
|
10
|
+
* (`h-*`, ou um pai flex com altura definida), encolhe e as linhas rolam por dentro; sem limite,
|
|
11
|
+
* cresce e só rola na horizontal. Um pai só com `max-height` não basta: o viewport não resolve a
|
|
12
|
+
* altura dele, e as linhas além do limite ficam cortadas, sem rolagem.
|
|
11
13
|
*
|
|
12
|
-
* As barras ficam numa faixa fora da moldura
|
|
13
|
-
*
|
|
14
|
-
* cuja altura é medida
|
|
14
|
+
* As barras ficam numa faixa fora da moldura: não passam por cima das linhas, da seleção nem das
|
|
15
|
+
* colunas fixadas. A faixa fica reservada nos dois eixos mesmo sem transbordo, e fica vazia
|
|
16
|
+
* quando não há o que rolar. A vertical começa abaixo do `DataTable.Header`, cuja altura é medida
|
|
17
|
+
* aqui.
|
|
18
|
+
*
|
|
19
|
+
* Monta também a barra de carga (`data-loading` do `DataTable.Root`) e a guia do resize, a linha
|
|
20
|
+
* que o `DataTable.ResizeHandle` mostra na altura toda da moldura (no vazio, só no cabeçalho). Os
|
|
21
|
+
* dois são internos: o
|
|
22
|
+
* `data-component="DataTable.ResizeGuide"` da guia não é uma parte pública, e ninguém precisa
|
|
23
|
+
* lê-lo.
|
|
15
24
|
*/
|
|
16
25
|
export declare const DataTableScrollArea: {
|
|
17
26
|
(props: DataTableScrollAreaProps): import("react").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table-scroll-area.d.ts","names":[],"sources":["../../../../src/components/data-table/root/data-table-scroll-area.tsx"],"mappings":";;YASY,2BAA2B,WAAW
|
|
1
|
+
{"version":3,"file":"data-table-scroll-area.d.ts","names":[],"sources":["../../../../src/components/data-table/root/data-table-scroll-area.tsx"],"mappings":";;YASY,2BAA2B,WAAW;;;;;;;;;;;;;;;;;;;;;;qBAuBrC;GAA8B,OAAA,2CAAwB,IAAA"}
|
|
@@ -10,12 +10,21 @@ import { mergeRefs } from "@lucasbernardosn/react-utils";
|
|
|
10
10
|
* borda, `Viewport`, `Content` e as barras. Os filhos vão no `Content`, e as props no `Root`.
|
|
11
11
|
*
|
|
12
12
|
* O viewport é o ancestral que rola, e é nele que o cabeçalho sticky se ancora. Na largura,
|
|
13
|
-
* abraça o grid e para no pai. Na altura, tem a das linhas: dentro de um pai com altura
|
|
14
|
-
*
|
|
13
|
+
* abraça o grid e para no pai. Na altura, tem a das linhas: dentro de um pai com altura definida
|
|
14
|
+
* (`h-*`, ou um pai flex com altura definida), encolhe e as linhas rolam por dentro; sem limite,
|
|
15
|
+
* cresce e só rola na horizontal. Um pai só com `max-height` não basta: o viewport não resolve a
|
|
16
|
+
* altura dele, e as linhas além do limite ficam cortadas, sem rolagem.
|
|
15
17
|
*
|
|
16
|
-
* As barras ficam numa faixa fora da moldura
|
|
17
|
-
*
|
|
18
|
-
* cuja altura é medida
|
|
18
|
+
* As barras ficam numa faixa fora da moldura: não passam por cima das linhas, da seleção nem das
|
|
19
|
+
* colunas fixadas. A faixa fica reservada nos dois eixos mesmo sem transbordo, e fica vazia
|
|
20
|
+
* quando não há o que rolar. A vertical começa abaixo do `DataTable.Header`, cuja altura é medida
|
|
21
|
+
* aqui.
|
|
22
|
+
*
|
|
23
|
+
* Monta também a barra de carga (`data-loading` do `DataTable.Root`) e a guia do resize, a linha
|
|
24
|
+
* que o `DataTable.ResizeHandle` mostra na altura toda da moldura (no vazio, só no cabeçalho). Os
|
|
25
|
+
* dois são internos: o
|
|
26
|
+
* `data-component="DataTable.ResizeGuide"` da guia não é uma parte pública, e ninguém precisa
|
|
27
|
+
* lê-lo.
|
|
19
28
|
*/
|
|
20
29
|
const DataTableScrollArea = (props) => {
|
|
21
30
|
const { className, children, ref, ...rest } = props;
|
|
@@ -35,8 +44,8 @@ const DataTableScrollArea = (props) => {
|
|
|
35
44
|
"[--scroll-area-scrollbar-inset:0px]",
|
|
36
45
|
"[--scroll-area-thumb-size:--spacing(1)]",
|
|
37
46
|
"pointer-fine:[--scroll-area-thumb-size:--spacing(1.5)]",
|
|
38
|
-
"
|
|
39
|
-
"
|
|
47
|
+
"pe-(--scroll-area-scrollbar-size)",
|
|
48
|
+
"pb-(--scroll-area-scrollbar-size)"
|
|
40
49
|
], className),
|
|
41
50
|
...rest,
|
|
42
51
|
children: [
|
|
@@ -92,6 +101,7 @@ const DataTableScrollArea = (props) => {
|
|
|
92
101
|
"group-has-[[data-component='DataTable.ResizeHandle']:hover]/data-table-frame:block",
|
|
93
102
|
"group-has-[[data-component='DataTable.ResizeHandle'][data-resizing]]/data-table-frame:block",
|
|
94
103
|
"not-supports-[anchor-name:--a]:hidden!",
|
|
104
|
+
"group-has-[[data-component='DataTable.Empty']]/data-table-frame:hidden!",
|
|
95
105
|
"pointer-events-none",
|
|
96
106
|
"absolute",
|
|
97
107
|
"inset-y-0",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table-scroll-area.js","names":[],"sources":["../../../../src/components/data-table/root/data-table-scroll-area.tsx"],"sourcesContent":["import { ScrollArea } from '@lucasbernardosn/react-ui/layout/scroll-area';\nimport {\n mergeStateClassNames,\n mergeTwClassNames,\n} from '@lucasbernardosn/react-ui/utils';\nimport { mergeRefs } from '@lucasbernardosn/react-utils';\nimport { useMemo } from 'react';\nimport { useDataTableHeaderOffset } from './use-data-table-header-offset';\n\nexport type DataTableScrollAreaProps = ScrollArea.RootProps;\n\n/**\n * A área de rolagem da tabela, montada com o `ScrollArea` da lib: `Root`, uma moldura com a\n * borda, `Viewport`, `Content` e as barras. Os filhos vão no `Content`, e as props no `Root`.\n *\n * O viewport é o ancestral que rola, e é nele que o cabeçalho sticky se ancora. Na largura,\n * abraça o grid e para no pai. Na altura, tem a das linhas: dentro de um pai com altura\n * limitada, encolhe e as linhas rolam por dentro; sem limite, cresce e só rola na horizontal.\n *\n * As barras ficam numa faixa fora da moldura, só no eixo que transborda: não passam por cima das\n * linhas, da seleção nem das colunas fixadas. A vertical começa abaixo do `DataTable.Header`,\n * cuja altura é medida aqui.\n */\nexport const DataTableScrollArea = (props: DataTableScrollAreaProps) => {\n const { className, children, ref, ...rest } = props;\n\n const headerOffsetRef = useDataTableHeaderOffset();\n\n /**\n * O ref de quem usa e o da medida do cabeçalho, no mesmo elemento. Memoizado: um callback novo\n * a cada render desligaria e religaria o observer.\n */\n const rootRef = useMemo(\n () => mergeRefs(headerOffsetRef, ref),\n [headerOffsetRef, ref],\n );\n\n return (\n <ScrollArea.Root\n ref={rootRef}\n data-component=\"DataTable.ScrollArea\"\n className={mergeStateClassNames(\n [\n // Sem `flex-1`: a altura é a das linhas, e o `flex-shrink` do item para no pai. O\n // `overflow-hidden` do `ScrollArea.Root` zera o mínimo, e as linhas passam a rolar.\n\n // Abraça o grid, que mede pelo `min-width: fit-content` do `Content`, mais a faixa das\n // barras, e para no pai.\n 'w-max',\n 'max-w-full',\n\n // A faixa das barras: 12px sem recuo, com o polegar mais fino centralizado nela.\n '[--scroll-area-scrollbar-size:--spacing(3)]',\n '[--scroll-area-scrollbar-inset:0px]',\n '[--scroll-area-thumb-size:--spacing(1)]',\n 'pointer-fine:[--scroll-area-thumb-size:--spacing(1.5)]',\n\n // A faixa só existe no eixo que transborda. O Base UI põe as barras nas bordas do\n // `Root`, que com o padding caem fora da moldura.\n 'data-has-overflow-y:pe-(--scroll-area-scrollbar-size)',\n 'data-has-overflow-x:pb-(--scroll-area-scrollbar-size)',\n ],\n className,\n )}\n {...rest}\n >\n <div\n className={mergeTwClassNames([\n // A altura do `Root` sem a faixa de baixo, para o viewport rolar dentro dela.\n 'h-full',\n\n // Referência da barra do carregamento, que se posiciona aqui e lê o `data-loading` do grid.\n 'relative',\n 'group/data-table-frame',\n\n // A borda cerca só a tabela, e não a faixa das barras. Num elemento que não rola: no\n // viewport, ela subiria junto com as linhas. O `overflow-clip` recorta o cabeçalho\n // sticky contra o raio sem virar contêiner de rolagem, e o sticky segue no viewport.\n 'overflow-clip',\n 'rounded-md',\n 'corner-squircle',\n 'border',\n 'border-gray-6',\n\n // O anel do viewport, que se marca com `data-focus-ring`: o tema o pinta no pai\n // direto, que é esta moldura, e não mais o `Root`.\n 'focus-ring-inside',\n '[--focus-ring-offset:-1px]',\n 'ring-gray-12',\n ])}\n >\n <ScrollArea.Viewport\n focusRing={true}\n // O arrasto horizontal no fim do curso não vira \"voltar página\"; o eixo Y fica livre\n // para o pull to refresh. O `scroll-padding-top` faz a linha que recebe o foco parar\n // abaixo do cabeçalho sticky, e não embaixo dele.\n className=\"overscroll-x-contain scroll-pt-(--data-table-header-offset)\"\n >\n <ScrollArea.Content>{children}</ScrollArea.Content>\n </ScrollArea.Viewport>\n\n <div\n aria-hidden={true}\n data-component=\"DataTable.LoadingBar\"\n className={mergeTwClassNames([\n // A barra do carregamento (`data-loading` no `DataTable.Root`), na borda de baixo do\n // cabeçalho. Na moldura, e não no cabeçalho: não acompanha a rolagem horizontal e\n // cobre sempre a largura visível. O seletor nomeia o `Root`: o `Skeleton` do `ui`\n // também marca `data-loading`, e um dentro de uma célula acenderia a barra.\n 'hidden',\n \"group-has-[[data-component='DataTable.Root'][data-loading]]/data-table-frame:block\",\n 'pointer-events-none',\n 'absolute',\n 'inset-x-0',\n 'top-[calc(var(--data-table-header-offset,0px)-1px)]',\n 'z-30',\n 'h-0.5',\n 'overflow-hidden',\n\n // Sem progresso real, um trecho corre de um lado ao outro, sem pausa. A animação do\n // tema pede o trecho com 2/5 da largura. Com movimento reduzido, a barra fica parada\n // e inteira.\n \"before:content-['']\",\n 'before:absolute',\n 'before:inset-y-0',\n 'before:w-2/5',\n 'before:rounded-full',\n 'before:bg-gray-11',\n 'not-motion-reduced:before:animate-progress-indeterminate',\n 'motion-reduced:before:w-full',\n 'motion-reduced:before:bg-gray-8',\n ])}\n />\n\n <div\n aria-hidden={true}\n data-component=\"DataTable.ResizeGuide\"\n className={mergeTwClassNames([\n // A linha-guia do resize, na altura toda da tabela, presa à linha vertical da coluna\n // pela âncora que o `DataTable.ResizeHandle` marca no hover e no arrasto. Na moldura e\n // acima das fixadas: a borda da coluna pode passar por baixo de uma fixada, e a guia\n // segue à vista.\n 'hidden',\n \"group-has-[[data-component='DataTable.ResizeHandle']:hover]/data-table-frame:block\",\n \"group-has-[[data-component='DataTable.ResizeHandle'][data-resizing]]/data-table-frame:block\",\n // Sem anchor positioning, a guia ficaria no canto da moldura: fica só a linha do\n // handle, no cabeçalho.\n 'not-supports-[anchor-name:--a]:hidden!',\n 'pointer-events-none',\n 'absolute',\n 'inset-y-0',\n 'z-30',\n // No lugar da linha do handle: centrada nele, sobre a borda e 1px antes dela.\n 'w-0.5',\n 'left-[anchor(left)]',\n '-translate-x-1/2',\n '[position-anchor:--data-table-resize-handle]',\n 'bg-gray-9',\n \"group-has-[[data-component='DataTable.ResizeHandle'][data-resizing]]/data-table-frame:bg-black\",\n \"dark:group-has-[[data-component='DataTable.ResizeHandle'][data-resizing]]/data-table-frame:bg-white\",\n ])}\n />\n </div>\n\n <ScrollArea.Scrollbar\n orientation=\"vertical\"\n // Começa abaixo do cabeçalho sticky, na altura da primeira linha: a do cabeçalho mais a\n // borda de cima da moldura.\n className=\"mt-[calc(var(--data-table-header-offset,0px)+1px)]\"\n >\n <ScrollArea.Thumb />\n </ScrollArea.Scrollbar>\n\n <ScrollArea.Scrollbar orientation=\"horizontal\">\n <ScrollArea.Thumb />\n </ScrollArea.Scrollbar>\n\n <ScrollArea.Corner />\n </ScrollArea.Root>\n );\n};\n\nDataTableScrollArea.displayName = 'DataTable.ScrollArea';\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAuBA,MAAa,uBAAuB,UAAoC;CACtE,MAAM,EAAE,WAAW,UAAU,KAAK,GAAG,SAAS;CAE9C,MAAM,kBAAkB,yBAAyB;;;;;CAMjD,MAAM,UAAU,cACR,UAAU,iBAAiB,GAAG,GACpC,CAAC,iBAAiB,GAAG,CACvB;CAEA,OACE,qBAAC,WAAW,MAAZ;EACE,KAAK;EACL,kBAAe;EACf,WAAW,qBACT;GAME;GACA;GAGA;GACA;GACA;GACA;GAIA;GACA;EACF,GACA,SACF;EACA,GAAI;EA1BN,UAAA;GA4BE,qBAAC,OAAD;IACE,WAAW,kBAAkB;KAE3B;KAGA;KACA;KAKA;KACA;KACA;KACA;KACA;KAIA;KACA;KACA;IACF,CAAC;IAvBH,UAAA;KAyBE,oBAAC,WAAW,UAAZ;MACE,WAAW;MAIX,WAAU;MAEV,UAAA,oBAAC,WAAW,SAAZ,EAAqB,SAA6B,CAAA;KAC/B,CAAA;KAErB,oBAAC,OAAD;MACE,eAAa;MACb,kBAAe;MACf,WAAW,kBAAkB;OAK3B;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OAKA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;MACF,CAAC;KACF,CAAA;KAED,oBAAC,OAAD;MACE,eAAa;MACb,kBAAe;MACf,WAAW,kBAAkB;OAK3B;OACA;OACA;OAGA;OACA;OACA;OACA;OACA;OAEA;OACA;OACA;OACA;OACA;OACA;OACA;MACF,CAAC;KACF,CAAA;IACE;;GAEL,oBAAC,WAAW,WAAZ;IACE,aAAY;IAGZ,WAAU;IAEV,UAAA,oBAAC,WAAW,OAAZ,CAAmB,CAAA;GACC,CAAA;GAEtB,oBAAC,WAAW,WAAZ;IAAsB,aAAY;IAChC,UAAA,oBAAC,WAAW,OAAZ,CAAmB,CAAA;GACC,CAAA;GAEtB,oBAAC,WAAW,QAAZ,CAAoB,CAAA;EACL;;AAErB;AAEA,oBAAoB,cAAc"}
|
|
1
|
+
{"version":3,"file":"data-table-scroll-area.js","names":[],"sources":["../../../../src/components/data-table/root/data-table-scroll-area.tsx"],"sourcesContent":["import { ScrollArea } from '@lucasbernardosn/react-ui/layout/scroll-area';\nimport {\n mergeStateClassNames,\n mergeTwClassNames,\n} from '@lucasbernardosn/react-ui/utils';\nimport { mergeRefs } from '@lucasbernardosn/react-utils';\nimport { useMemo } from 'react';\nimport { useDataTableHeaderOffset } from './use-data-table-header-offset';\n\nexport type DataTableScrollAreaProps = ScrollArea.RootProps;\n\n/**\n * A área de rolagem da tabela, montada com o `ScrollArea` da lib: `Root`, uma moldura com a\n * borda, `Viewport`, `Content` e as barras. Os filhos vão no `Content`, e as props no `Root`.\n *\n * O viewport é o ancestral que rola, e é nele que o cabeçalho sticky se ancora. Na largura,\n * abraça o grid e para no pai. Na altura, tem a das linhas: dentro de um pai com altura definida\n * (`h-*`, ou um pai flex com altura definida), encolhe e as linhas rolam por dentro; sem limite,\n * cresce e só rola na horizontal. Um pai só com `max-height` não basta: o viewport não resolve a\n * altura dele, e as linhas além do limite ficam cortadas, sem rolagem.\n *\n * As barras ficam numa faixa fora da moldura: não passam por cima das linhas, da seleção nem das\n * colunas fixadas. A faixa fica reservada nos dois eixos mesmo sem transbordo, e fica vazia\n * quando não há o que rolar. A vertical começa abaixo do `DataTable.Header`, cuja altura é medida\n * aqui.\n *\n * Monta também a barra de carga (`data-loading` do `DataTable.Root`) e a guia do resize, a linha\n * que o `DataTable.ResizeHandle` mostra na altura toda da moldura (no vazio, só no cabeçalho). Os\n * dois são internos: o\n * `data-component=\"DataTable.ResizeGuide\"` da guia não é uma parte pública, e ninguém precisa\n * lê-lo.\n */\nexport const DataTableScrollArea = (props: DataTableScrollAreaProps) => {\n const { className, children, ref, ...rest } = props;\n\n const headerOffsetRef = useDataTableHeaderOffset();\n\n /**\n * O ref de quem usa e o da medida do cabeçalho, no mesmo elemento. Memoizado: um callback novo\n * a cada render desligaria e religaria o observer.\n */\n const rootRef = useMemo(\n () => mergeRefs(headerOffsetRef, ref),\n [headerOffsetRef, ref],\n );\n\n return (\n <ScrollArea.Root\n ref={rootRef}\n data-component=\"DataTable.ScrollArea\"\n className={mergeStateClassNames(\n [\n // Sem `flex-1`: a altura é a das linhas, e o `flex-shrink` do item para no pai. O\n // `overflow-hidden` do `ScrollArea.Root` zera o mínimo, e as linhas passam a rolar.\n\n // Abraça o grid, que mede pelo `min-width: fit-content` do `Content`, mais a faixa das\n // barras, e para no pai.\n 'w-max',\n 'max-w-full',\n\n // A faixa das barras: 12px sem recuo, com o polegar mais fino centralizado nela.\n '[--scroll-area-scrollbar-size:--spacing(3)]',\n '[--scroll-area-scrollbar-inset:0px]',\n '[--scroll-area-thumb-size:--spacing(1)]',\n 'pointer-fine:[--scroll-area-thumb-size:--spacing(1.5)]',\n\n // A faixa reservada nos dois eixos, com ou sem transbordo: só no eixo que transborda, ela\n // entraria quando as linhas ou as colunas passam do espaço, e a moldura saltaria 12px. O\n // Base UI põe as barras nas bordas do `Root`, que com o padding caem fora da moldura.\n 'pe-(--scroll-area-scrollbar-size)',\n 'pb-(--scroll-area-scrollbar-size)',\n ],\n className,\n )}\n {...rest}\n >\n <div\n className={mergeTwClassNames([\n // A altura do `Root` sem a faixa de baixo, para o viewport rolar dentro dela.\n 'h-full',\n\n // Referência da barra do carregamento, que se posiciona aqui e lê o `data-loading` do grid.\n 'relative',\n 'group/data-table-frame',\n\n // A borda cerca só a tabela, e não a faixa das barras. Num elemento que não rola: no\n // viewport, ela subiria junto com as linhas. O `overflow-clip` recorta o cabeçalho\n // sticky contra o raio sem virar contêiner de rolagem, e o sticky segue no viewport.\n 'overflow-clip',\n 'rounded-md',\n 'corner-squircle',\n 'border',\n 'border-gray-6',\n\n // O anel do viewport, que se marca com `data-focus-ring`: o tema o pinta no pai\n // direto, que é esta moldura, e não mais o `Root`.\n 'focus-ring-inside',\n '[--focus-ring-offset:-1px]',\n 'ring-gray-12',\n ])}\n >\n <ScrollArea.Viewport\n focusRing={true}\n // O arrasto horizontal no fim do curso não vira \"voltar página\"; o eixo Y fica livre\n // para o pull to refresh. O `scroll-padding-top` faz a linha que recebe o foco parar\n // abaixo do cabeçalho sticky, e não embaixo dele.\n className=\"overscroll-x-contain scroll-pt-(--data-table-header-offset)\"\n >\n <ScrollArea.Content>{children}</ScrollArea.Content>\n </ScrollArea.Viewport>\n\n <div\n aria-hidden={true}\n data-component=\"DataTable.LoadingBar\"\n className={mergeTwClassNames([\n // A barra do carregamento (`data-loading` no `DataTable.Root`), na borda de baixo do\n // cabeçalho. Na moldura, e não no cabeçalho: não acompanha a rolagem horizontal e\n // cobre sempre a largura visível. O seletor nomeia o `Root`: o `Skeleton` do `ui`\n // também marca `data-loading`, e um dentro de uma célula acenderia a barra.\n 'hidden',\n \"group-has-[[data-component='DataTable.Root'][data-loading]]/data-table-frame:block\",\n 'pointer-events-none',\n 'absolute',\n 'inset-x-0',\n 'top-[calc(var(--data-table-header-offset,0px)-1px)]',\n 'z-30',\n 'h-0.5',\n 'overflow-hidden',\n\n // Sem progresso real, um trecho corre de um lado ao outro, sem pausa. A animação do\n // tema pede o trecho com 2/5 da largura. Com movimento reduzido, a barra fica parada\n // e inteira.\n \"before:content-['']\",\n 'before:absolute',\n 'before:inset-y-0',\n 'before:w-2/5',\n 'before:rounded-full',\n 'before:bg-gray-11',\n 'not-motion-reduced:before:animate-progress-indeterminate',\n 'motion-reduced:before:w-full',\n 'motion-reduced:before:bg-gray-8',\n ])}\n />\n\n <div\n aria-hidden={true}\n data-component=\"DataTable.ResizeGuide\"\n className={mergeTwClassNames([\n // A linha-guia do resize, na altura toda da tabela, presa à linha vertical da coluna\n // pela âncora que o `DataTable.ResizeHandle` marca no hover e no arrasto. Na moldura e\n // acima das fixadas: a borda da coluna pode passar por baixo de uma fixada, e a guia\n // segue à vista.\n 'hidden',\n \"group-has-[[data-component='DataTable.ResizeHandle']:hover]/data-table-frame:block\",\n \"group-has-[[data-component='DataTable.ResizeHandle'][data-resizing]]/data-table-frame:block\",\n // Sem anchor positioning, a guia ficaria no canto da moldura: fica só a linha do\n // handle, no cabeçalho. No vazio também: sem linhas, a guia cortaria a mensagem ao meio.\n 'not-supports-[anchor-name:--a]:hidden!',\n \"group-has-[[data-component='DataTable.Empty']]/data-table-frame:hidden!\",\n 'pointer-events-none',\n 'absolute',\n 'inset-y-0',\n 'z-30',\n // No lugar da linha do handle: centrada nele, sobre a borda e 1px antes dela.\n 'w-0.5',\n 'left-[anchor(left)]',\n '-translate-x-1/2',\n '[position-anchor:--data-table-resize-handle]',\n 'bg-gray-9',\n \"group-has-[[data-component='DataTable.ResizeHandle'][data-resizing]]/data-table-frame:bg-black\",\n \"dark:group-has-[[data-component='DataTable.ResizeHandle'][data-resizing]]/data-table-frame:bg-white\",\n ])}\n />\n </div>\n\n <ScrollArea.Scrollbar\n orientation=\"vertical\"\n // Começa abaixo do cabeçalho sticky, na altura da primeira linha: a do cabeçalho mais a\n // borda de cima da moldura.\n className=\"mt-[calc(var(--data-table-header-offset,0px)+1px)]\"\n >\n <ScrollArea.Thumb />\n </ScrollArea.Scrollbar>\n\n <ScrollArea.Scrollbar orientation=\"horizontal\">\n <ScrollArea.Thumb />\n </ScrollArea.Scrollbar>\n\n <ScrollArea.Corner />\n </ScrollArea.Root>\n );\n};\n\nDataTableScrollArea.displayName = 'DataTable.ScrollArea';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,MAAa,uBAAuB,UAAoC;CACtE,MAAM,EAAE,WAAW,UAAU,KAAK,GAAG,SAAS;CAE9C,MAAM,kBAAkB,yBAAyB;;;;;CAMjD,MAAM,UAAU,cACR,UAAU,iBAAiB,GAAG,GACpC,CAAC,iBAAiB,GAAG,CACvB;CAEA,OACE,qBAAC,WAAW,MAAZ;EACE,KAAK;EACL,kBAAe;EACf,WAAW,qBACT;GAME;GACA;GAGA;GACA;GACA;GACA;GAKA;GACA;EACF,GACA,SACF;EACA,GAAI;EA3BN,UAAA;GA6BE,qBAAC,OAAD;IACE,WAAW,kBAAkB;KAE3B;KAGA;KACA;KAKA;KACA;KACA;KACA;KACA;KAIA;KACA;KACA;IACF,CAAC;IAvBH,UAAA;KAyBE,oBAAC,WAAW,UAAZ;MACE,WAAW;MAIX,WAAU;MAEV,UAAA,oBAAC,WAAW,SAAZ,EAAqB,SAA6B,CAAA;KAC/B,CAAA;KAErB,oBAAC,OAAD;MACE,eAAa;MACb,kBAAe;MACf,WAAW,kBAAkB;OAK3B;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OAKA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;MACF,CAAC;KACF,CAAA;KAED,oBAAC,OAAD;MACE,eAAa;MACb,kBAAe;MACf,WAAW,kBAAkB;OAK3B;OACA;OACA;OAGA;OACA;OACA;OACA;OACA;OACA;OAEA;OACA;OACA;OACA;OACA;OACA;OACA;MACF,CAAC;KACF,CAAA;IACE;;GAEL,oBAAC,WAAW,WAAZ;IACE,aAAY;IAGZ,WAAU;IAEV,UAAA,oBAAC,WAAW,OAAZ,CAAmB,CAAA;GACC,CAAA;GAEtB,oBAAC,WAAW,WAAZ;IAAsB,aAAY;IAChC,UAAA,oBAAC,WAAW,OAAZ,CAAmB,CAAA;GACC,CAAA;GAEtB,oBAAC,WAAW,QAAZ,CAAoB,CAAA;EACL;;AAErB;AAEA,oBAAoB,cAAc"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { TableWith } from "../../../types/table-with.js";
|
|
2
|
+
import "../../../types/index.js";
|
|
3
|
+
import { RowData, TableFeatures } from "@tanstack/react-table";
|
|
4
|
+
import React from "react";
|
|
5
|
+
import { ActionBar } from "@lucasbernardosn/react-ui/overlays/action-bar";
|
|
6
|
+
import { MergeOverride } from "@lucasbernardosn/utils";
|
|
7
|
+
//#region src/components/data-table/selection/data-table-selection-bar.d.ts
|
|
8
|
+
export type DataTableSelectionBarProps<TFeatures extends TableFeatures, TData extends RowData> = MergeOverride<ActionBar.PopupProps, {
|
|
9
|
+
/** A tabela. Exige `rowSelectionFeature`. */
|
|
10
|
+
table: TableWith<TFeatures, TData, 'rowSelectionFeature'>;
|
|
11
|
+
/**
|
|
12
|
+
* As ações da seleção. Recebe os ids das linhas marcadas, inclusive os de outras páginas e os
|
|
13
|
+
* de linhas que não estão carregadas: o app resolve o id para o registro.
|
|
14
|
+
*/
|
|
15
|
+
children?: (selectedIds: string[]) => React.ReactNode;
|
|
16
|
+
/** A posição da barra no rodapé da tela. */
|
|
17
|
+
placement?: ActionBar.RootProps['placement'];
|
|
18
|
+
/**
|
|
19
|
+
* O texto lido pelo leitor de tela no resumo, que limpa a seleção.
|
|
20
|
+
* @default 'Limpar seleção'
|
|
21
|
+
*/
|
|
22
|
+
clearLabel?: string;
|
|
23
|
+
}>;
|
|
24
|
+
/**
|
|
25
|
+
* A barra de ações da seleção, fixa no rodapé da tela: aparece com ao menos uma linha marcada e
|
|
26
|
+
* some ao limpar. Monta o `ActionBar` do `ui` e liga à tabela o que é igual em toda lista: a
|
|
27
|
+
* abertura pela contagem, o texto do resumo e a limpeza da seleção.
|
|
28
|
+
*
|
|
29
|
+
* O resumo ("3 selecionadas") é o botão que limpa a seleção, e o Esc também a limpa. As ações são
|
|
30
|
+
* do app: entram como `children`, que recebe os ids marcados. A barra não confirma nada nem sabe
|
|
31
|
+
* o que as ações fazem.
|
|
32
|
+
*
|
|
33
|
+
* Os ids vêm do estado da seleção e valem para toda a tabela, e não só para a página à vista.
|
|
34
|
+
* Quando um filtro muda as linhas, a seleção continua com ids que sumiram da tela: quem filtra
|
|
35
|
+
* decide se a limpa (`table.resetRowSelection()`).
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```tsx
|
|
39
|
+
* <DataTable.SelectionBar table={table}>
|
|
40
|
+
* {(selectedIds) => (
|
|
41
|
+
* <Button onClick={() => removeAll(selectedIds)}>Excluir</Button>
|
|
42
|
+
* )}
|
|
43
|
+
* </DataTable.SelectionBar>
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare const DataTableSelectionBar: {
|
|
47
|
+
<TFeatures extends TableFeatures, TData extends RowData>(props: DataTableSelectionBarProps<TFeatures, TData>): React.JSX.Element;
|
|
48
|
+
displayName: string;
|
|
49
|
+
};
|
|
50
|
+
//#endregion
|
|
51
|
+
//# sourceMappingURL=data-table-selection-bar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-table-selection-bar.d.ts","names":[],"sources":["../../../../src/components/data-table/selection/data-table-selection-bar.tsx"],"mappings":";;;;;;;YAQY,2BACV,kBAAkB,eAClB,cAAc,WACZ,cACF,UAAU;;EAGR,OAAO,UAAU,WAAW;;;;;EAK5B,YAAY,0BAA0B,MAAM;;EAE5C,YAAY,UAAU;;;;;EAKtB;;;;;;;;;;;;;;;;;;;;;;;;qBA0BS;GACX,kBAAkB,eAClB,cAAc,SAAO,OAEd,2BAA2B,WAAW,SAAM,MAAA,IAAA"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { DataTableSelectedCount } from "../pagination/data-table-selected-count.js";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useSelector } from "@tanstack/react-store";
|
|
4
|
+
import { ActionBar } from "@lucasbernardosn/react-ui/overlays/action-bar";
|
|
5
|
+
//#region src/components/data-table/selection/data-table-selection-bar.tsx
|
|
6
|
+
/**
|
|
7
|
+
* A barra de ações da seleção, fixa no rodapé da tela: aparece com ao menos uma linha marcada e
|
|
8
|
+
* some ao limpar. Monta o `ActionBar` do `ui` e liga à tabela o que é igual em toda lista: a
|
|
9
|
+
* abertura pela contagem, o texto do resumo e a limpeza da seleção.
|
|
10
|
+
*
|
|
11
|
+
* O resumo ("3 selecionadas") é o botão que limpa a seleção, e o Esc também a limpa. As ações são
|
|
12
|
+
* do app: entram como `children`, que recebe os ids marcados. A barra não confirma nada nem sabe
|
|
13
|
+
* o que as ações fazem.
|
|
14
|
+
*
|
|
15
|
+
* Os ids vêm do estado da seleção e valem para toda a tabela, e não só para a página à vista.
|
|
16
|
+
* Quando um filtro muda as linhas, a seleção continua com ids que sumiram da tela: quem filtra
|
|
17
|
+
* decide se a limpa (`table.resetRowSelection()`).
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```tsx
|
|
21
|
+
* <DataTable.SelectionBar table={table}>
|
|
22
|
+
* {(selectedIds) => (
|
|
23
|
+
* <Button onClick={() => removeAll(selectedIds)}>Excluir</Button>
|
|
24
|
+
* )}
|
|
25
|
+
* </DataTable.SelectionBar>
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
const DataTableSelectionBar = (props) => {
|
|
29
|
+
const { table, children, placement, clearLabel = "Limpar seleção", ...rest } = props;
|
|
30
|
+
/** Os ids marcados: o estado só guarda as linhas marcadas. Re-renderiza quando muda. */
|
|
31
|
+
const selectedIds = useSelector(table.atoms.rowSelection, (rowSelection) => Object.keys(rowSelection));
|
|
32
|
+
return /* @__PURE__ */ jsx(ActionBar.Root, {
|
|
33
|
+
placement,
|
|
34
|
+
open: selectedIds.length > 0,
|
|
35
|
+
onOpenChange: (open) => {
|
|
36
|
+
if (!open) table.resetRowSelection(true);
|
|
37
|
+
},
|
|
38
|
+
children: /* @__PURE__ */ jsx(ActionBar.Portal, { children: /* @__PURE__ */ jsxs(ActionBar.Popup, {
|
|
39
|
+
"data-component": "DataTable.SelectionBar",
|
|
40
|
+
...rest,
|
|
41
|
+
children: [/* @__PURE__ */ jsxs(ActionBar.SelectionTrigger, {
|
|
42
|
+
onClick: () => table.resetRowSelection(true),
|
|
43
|
+
children: [/* @__PURE__ */ jsx(DataTableSelectedCount, {
|
|
44
|
+
table,
|
|
45
|
+
className: "text-gray-12"
|
|
46
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
47
|
+
className: "sr-only",
|
|
48
|
+
children: clearLabel
|
|
49
|
+
})]
|
|
50
|
+
}), children?.(selectedIds)]
|
|
51
|
+
}) })
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
DataTableSelectionBar.displayName = "DataTable.SelectionBar";
|
|
55
|
+
//#endregion
|
|
56
|
+
export { DataTableSelectionBar };
|
|
57
|
+
|
|
58
|
+
//# sourceMappingURL=data-table-selection-bar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-table-selection-bar.js","names":[],"sources":["../../../../src/components/data-table/selection/data-table-selection-bar.tsx"],"sourcesContent":["import { ActionBar } from '@lucasbernardosn/react-ui/overlays/action-bar';\nimport type { MergeOverride } from '@lucasbernardosn/utils';\nimport { useSelector } from '@tanstack/react-store';\nimport type { RowData, TableFeatures } from '@tanstack/react-table';\nimport type React from 'react';\nimport type { TableWith } from '../../../types';\nimport { DataTableSelectedCount } from '../pagination/data-table-selected-count';\n\nexport type DataTableSelectionBarProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n ActionBar.PopupProps,\n {\n /** A tabela. Exige `rowSelectionFeature`. */\n table: TableWith<TFeatures, TData, 'rowSelectionFeature'>;\n /**\n * As ações da seleção. Recebe os ids das linhas marcadas, inclusive os de outras páginas e os\n * de linhas que não estão carregadas: o app resolve o id para o registro.\n */\n children?: (selectedIds: string[]) => React.ReactNode;\n /** A posição da barra no rodapé da tela. */\n placement?: ActionBar.RootProps['placement'];\n /**\n * O texto lido pelo leitor de tela no resumo, que limpa a seleção.\n * @default 'Limpar seleção'\n */\n clearLabel?: string;\n }\n>;\n\n/**\n * A barra de ações da seleção, fixa no rodapé da tela: aparece com ao menos uma linha marcada e\n * some ao limpar. Monta o `ActionBar` do `ui` e liga à tabela o que é igual em toda lista: a\n * abertura pela contagem, o texto do resumo e a limpeza da seleção.\n *\n * O resumo (\"3 selecionadas\") é o botão que limpa a seleção, e o Esc também a limpa. As ações são\n * do app: entram como `children`, que recebe os ids marcados. A barra não confirma nada nem sabe\n * o que as ações fazem.\n *\n * Os ids vêm do estado da seleção e valem para toda a tabela, e não só para a página à vista.\n * Quando um filtro muda as linhas, a seleção continua com ids que sumiram da tela: quem filtra\n * decide se a limpa (`table.resetRowSelection()`).\n *\n * @example\n * ```tsx\n * <DataTable.SelectionBar table={table}>\n * {(selectedIds) => (\n * <Button onClick={() => removeAll(selectedIds)}>Excluir</Button>\n * )}\n * </DataTable.SelectionBar>\n * ```\n */\nexport const DataTableSelectionBar = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableSelectionBarProps<TFeatures, TData>,\n) => {\n const {\n table,\n children,\n placement,\n clearLabel = 'Limpar seleção',\n ...rest\n } = props;\n\n /** Os ids marcados: o estado só guarda as linhas marcadas. Re-renderiza quando muda. */\n const selectedIds = useSelector(table.atoms.rowSelection, (rowSelection) =>\n Object.keys(rowSelection),\n );\n\n return (\n <ActionBar.Root\n placement={placement}\n open={selectedIds.length > 0}\n onOpenChange={(open) => {\n if (!open) {\n table.resetRowSelection(true);\n }\n }}\n >\n <ActionBar.Portal>\n <ActionBar.Popup\n data-component=\"DataTable.SelectionBar\"\n {...rest}\n >\n <ActionBar.SelectionTrigger\n onClick={() => table.resetRowSelection(true)}\n >\n <DataTableSelectedCount\n table={table}\n className=\"text-gray-12\"\n />\n <span className=\"sr-only\">{clearLabel}</span>\n </ActionBar.SelectionTrigger>\n\n {children?.(selectedIds)}\n </ActionBar.Popup>\n </ActionBar.Portal>\n </ActionBar.Root>\n );\n};\n\nDataTableSelectionBar.displayName = 'DataTable.SelectionBar';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAqDA,MAAa,yBAIX,UACG;CACH,MAAM,EACJ,OACA,UACA,WACA,aAAa,kBACb,GAAG,SACD;;CAGJ,MAAM,cAAc,YAAY,MAAM,MAAM,eAAe,iBACzD,OAAO,KAAK,YAAY,CAC1B;CAEA,OACE,oBAAC,UAAU,MAAX;EACa;EACX,MAAM,YAAY,SAAS;EAC3B,eAAe,SAAS;GACtB,IAAI,CAAC,MACH,MAAM,kBAAkB,IAAI;EAEhC;EAEA,UAAA,oBAAC,UAAU,QAAX,EAAA,UACE,qBAAC,UAAU,OAAX;GACE,kBAAe;GACf,GAAI;GAFN,UAAA,CAIE,qBAAC,UAAU,kBAAX;IACE,eAAe,MAAM,kBAAkB,IAAI;IAD7C,UAAA,CAGE,oBAAC,wBAAD;KACS;KACP,WAAU;IACX,CAAA,GACD,oBAAC,QAAD;KAAM,WAAU;KAAW,UAAA;IAAiB,CAAA,CAClB;GAE3B,CAAA,GAAA,WAAW,WAAW,CACR;EACD,CAAA,EAAA,CAAA;CACJ,CAAA;AAEpB;AAEA,sBAAsB,cAAc"}
|
|
@@ -11,7 +11,7 @@ export type DataTableDensitySelectProps<TFeatures extends TableFeatures, TData e
|
|
|
11
11
|
table: TableWith<TFeatures, TData, 'rowDensityFeature'>;
|
|
12
12
|
/**
|
|
13
13
|
* O nome de cada densidade.
|
|
14
|
-
* @default { compact: 'Compacta', standard: 'Padrão',
|
|
14
|
+
* @default { compact: 'Compacta', standard: 'Padrão', airy: 'Arejada' }
|
|
15
15
|
*/
|
|
16
16
|
labels?: Partial<Record<RowDensity, string>>;
|
|
17
17
|
/**
|
|
@@ -5,12 +5,12 @@ import { Select } from "@lucasbernardosn/react-ui/collections/select";
|
|
|
5
5
|
const DEFAULT_LABELS = {
|
|
6
6
|
compact: "Compacta",
|
|
7
7
|
standard: "Padrão",
|
|
8
|
-
|
|
8
|
+
airy: "Arejada"
|
|
9
9
|
};
|
|
10
10
|
const DENSITIES = [
|
|
11
11
|
"compact",
|
|
12
12
|
"standard",
|
|
13
|
-
"
|
|
13
|
+
"airy"
|
|
14
14
|
];
|
|
15
15
|
/**
|
|
16
16
|
* O select da densidade das linhas, para a barra de ferramentas. Sem rótulo visível: o nome para
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table-density-select.js","names":[],"sources":["../../../../src/components/data-table/toolbar/data-table-density-select.tsx"],"sourcesContent":["import { Select } from '@lucasbernardosn/react-ui/collections/select';\nimport type { MergeOverride } from '@lucasbernardosn/utils';\nimport { useSelector } from '@tanstack/react-store';\nimport type { RowData, TableFeatures } from '@tanstack/react-table';\nimport type { RowDensity } from '../../../features';\nimport type { TableWith } from '../../../types';\n\nexport type DataTableDensitySelectProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n Select.TriggerProps,\n {\n /** A tabela. Exige `rowDensityFeature`. */\n table: TableWith<TFeatures, TData, 'rowDensityFeature'>;\n /**\n * O nome de cada densidade.\n * @default { compact: 'Compacta', standard: 'Padrão',
|
|
1
|
+
{"version":3,"file":"data-table-density-select.js","names":[],"sources":["../../../../src/components/data-table/toolbar/data-table-density-select.tsx"],"sourcesContent":["import { Select } from '@lucasbernardosn/react-ui/collections/select';\nimport type { MergeOverride } from '@lucasbernardosn/utils';\nimport { useSelector } from '@tanstack/react-store';\nimport type { RowData, TableFeatures } from '@tanstack/react-table';\nimport type { RowDensity } from '../../../features';\nimport type { TableWith } from '../../../types';\n\nexport type DataTableDensitySelectProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n Select.TriggerProps,\n {\n /** A tabela. Exige `rowDensityFeature`. */\n table: TableWith<TFeatures, TData, 'rowDensityFeature'>;\n /**\n * O nome de cada densidade.\n * @default { compact: 'Compacta', standard: 'Padrão', airy: 'Arejada' }\n */\n labels?: Partial<Record<RowDensity, string>>;\n /**\n * O tamanho do select.\n * @default 'sm'\n */\n size?: Select.RootProps<RowDensity>['size'];\n }\n>;\n\nconst DEFAULT_LABELS: Record<RowDensity, string> = {\n compact: 'Compacta',\n standard: 'Padrão',\n airy: 'Arejada',\n};\n\nconst DENSITIES: RowDensity[] = ['compact', 'standard', 'airy'];\n\n/**\n * O select da densidade das linhas, para a barra de ferramentas. Sem rótulo visível: o nome para\n * o leitor de tela é \"Densidade\", trocável pelo `aria-label`.\n *\n * Renderiza o `Select` do `ui` por dentro; as props passam para o trigger.\n *\n * @example\n * ```tsx\n * <DataTable.DensitySelect table={table} />\n * ```\n */\nexport const DataTableDensitySelect = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableDensitySelectProps<TFeatures, TData>,\n) => {\n const { table, labels, size = 'sm', disabled, ...rest } = props;\n\n /** Re-renderiza quando a densidade muda. */\n const density = useSelector(table.atoms.rowDensity);\n\n const items = DENSITIES.map((value) => ({\n label: labels?.[value] ?? DEFAULT_LABELS[value],\n value,\n }));\n\n return (\n <Select.Root<RowDensity>\n size={size}\n value={density}\n items={items}\n disabled={disabled}\n onValueChange={(value) => {\n if (value !== null) {\n table.setRowDensity(value);\n }\n }}\n >\n <Select.Trigger\n data-component=\"DataTable.DensitySelect\"\n aria-label=\"Densidade\"\n {...rest}\n >\n <Select.Value />\n <Select.Icon />\n </Select.Trigger>\n\n <Select.Portal>\n <Select.Positioner alignItemWithTrigger={false}>\n <Select.Popup>\n <Select.List>\n {items.map((item) => (\n <Select.Item\n key={item.value}\n value={item.value}\n >\n <Select.ItemIndicator />\n <Select.ItemText>{item.label}</Select.ItemText>\n </Select.Item>\n ))}\n </Select.List>\n </Select.Popup>\n </Select.Positioner>\n </Select.Portal>\n </Select.Root>\n );\n};\n\nDataTableDensitySelect.displayName = 'DataTable.DensitySelect';\n"],"mappings":";;;;AA4BA,MAAM,iBAA6C;CACjD,SAAS;CACT,UAAU;CACV,MAAM;AACR;AAEA,MAAM,YAA0B;CAAC;CAAW;CAAY;AAAM;;;;;;;;;;;;AAa9D,MAAa,0BAIX,UACG;CACH,MAAM,EAAE,OAAO,QAAQ,OAAO,MAAM,UAAU,GAAG,SAAS;;CAG1D,MAAM,UAAU,YAAY,MAAM,MAAM,UAAU;CAElD,MAAM,QAAQ,UAAU,KAAK,WAAW;EACtC,OAAO,SAAS,UAAU,eAAe;EACzC;CACF,EAAE;CAEF,OACE,qBAAC,OAAO,MAAR;EACQ;EACN,OAAO;EACA;EACG;EACV,gBAAgB,UAAU;GACxB,IAAI,UAAU,MACZ,MAAM,cAAc,KAAK;EAE7B;EATF,UAAA,CAWE,qBAAC,OAAO,SAAR;GACE,kBAAe;GACf,cAAW;GACX,GAAI;GAHN,UAAA,CAKE,oBAAC,OAAO,OAAR,CAAe,CAAA,GACf,oBAAC,OAAO,MAAR,CAAc,CAAA,CACA;EAEhB,CAAA,GAAA,oBAAC,OAAO,QAAR,EAAA,UACE,oBAAC,OAAO,YAAR;GAAmB,sBAAsB;GACvC,UAAA,oBAAC,OAAO,OAAR,EAAA,UACE,oBAAC,OAAO,MAAR,EAAA,UACG,MAAM,KAAK,SACV,qBAAC,OAAO,MAAR;IAEE,OAAO,KAAK;IAFd,UAAA,CAIE,oBAAC,OAAO,eAAR,CAAuB,CAAA,GACvB,oBAAC,OAAO,UAAR,EAAA,UAAkB,KAAK,MAAuB,CAAA,CACnC;GALN,GAAA,KAAK,KAKC,CACd,EACU,CAAA,EACD,CAAA;EACG,CAAA,EACN,CAAA,CACJ;;AAEjB;AAEA,uBAAuB,cAAc"}
|
|
@@ -26,7 +26,8 @@ export type DataTableSortColumnSelectProps<TFeatures extends TableFeatures, TDat
|
|
|
26
26
|
/**
|
|
27
27
|
* O select da coluna da ordenação, para onde o cabeçalho não serve de controle, como no celular.
|
|
28
28
|
* Lista as colunas visíveis que ordenam, e "Sem ordenação" no topo; a coluna da ordenação atual
|
|
29
|
-
* entra no fim mesmo escondida.
|
|
29
|
+
* entra no fim mesmo escondida. Com `enableSortingRemoval: false` na tabela, que deixa a lista
|
|
30
|
+
* sempre ordenada, o "Sem ordenação" não aparece. Escolher uma coluna troca a
|
|
30
31
|
* ordenação inteira por ela, na direção atual, ou na primeira da coluna sem ordenação antes. Com
|
|
31
32
|
* a ordenação por várias colunas, mostra a primeira.
|
|
32
33
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table-sort-column-select.d.ts","names":[],"sources":["../../../../src/components/data-table/toolbar/data-table-sort-column-select.tsx"],"mappings":";;;;;;YAWY,+BACV,kBAAkB,eAClB,cAAc,WACZ,cACF,OAAO;;EAGL,OAAO,UAAU,WAAW;;;;;EAK5B,YAAY,QAAQ,OAAO,WAAW;;;;;EAKtC;;;;;EAKA,OAAO,OAAO
|
|
1
|
+
{"version":3,"file":"data-table-sort-column-select.d.ts","names":[],"sources":["../../../../src/components/data-table/toolbar/data-table-sort-column-select.tsx"],"mappings":";;;;;;YAWY,+BACV,kBAAkB,eAClB,cAAc,WACZ,cACF,OAAO;;EAGL,OAAO,UAAU,WAAW;;;;;EAK5B,YAAY,QAAQ,OAAO,WAAW;;;;;EAKtC;;;;;EAKA,OAAO,OAAO;;;;;;;;;;;;;;;;;;;qBAwBL;GACX,kBAAkB,eAClB,cAAc,SAAO,OAEd,+BAA+B,WAAW,yBAAM,IAAA"}
|
|
@@ -9,7 +9,8 @@ const NO_SORTING = "";
|
|
|
9
9
|
/**
|
|
10
10
|
* O select da coluna da ordenação, para onde o cabeçalho não serve de controle, como no celular.
|
|
11
11
|
* Lista as colunas visíveis que ordenam, e "Sem ordenação" no topo; a coluna da ordenação atual
|
|
12
|
-
* entra no fim mesmo escondida.
|
|
12
|
+
* entra no fim mesmo escondida. Com `enableSortingRemoval: false` na tabela, que deixa a lista
|
|
13
|
+
* sempre ordenada, o "Sem ordenação" não aparece. Escolher uma coluna troca a
|
|
13
14
|
* ordenação inteira por ela, na direção atual, ou na primeira da coluna sem ordenação antes. Com
|
|
14
15
|
* a ordenação por várias colunas, mostra a primeira.
|
|
15
16
|
*
|
|
@@ -32,10 +33,10 @@ const DataTableSortColumnSelect = (props) => {
|
|
|
32
33
|
* usuário mas ordenada pelo código. Sem ela, o trigger mostraria o id.
|
|
33
34
|
*/
|
|
34
35
|
const sortedColumn = sortedColumnId === NO_SORTING || sortableColumns.some((column) => column.id === sortedColumnId) ? void 0 : table.getColumn(sortedColumnId);
|
|
35
|
-
const items = [{
|
|
36
|
+
const items = [...table.options.enableSortingRemoval !== false ? [{
|
|
36
37
|
label: noSortingLabel,
|
|
37
38
|
value: NO_SORTING
|
|
38
|
-
}, ...[...sortableColumns, ...sortedColumn ? [sortedColumn] : []].map((column) => ({
|
|
39
|
+
}] : [], ...[...sortableColumns, ...sortedColumn ? [sortedColumn] : []].map((column) => ({
|
|
39
40
|
label: getLabel(column),
|
|
40
41
|
value: column.id
|
|
41
42
|
}))];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table-sort-column-select.js","names":[],"sources":["../../../../src/components/data-table/toolbar/data-table-sort-column-select.tsx"],"sourcesContent":["import { Select } from '@lucasbernardosn/react-ui/collections/select';\nimport type { MergeOverride } from '@lucasbernardosn/utils';\nimport { useSelector } from '@tanstack/react-store';\nimport type { Column, RowData, TableFeatures } from '@tanstack/react-table';\nimport type { TableWith } from '../../../types';\nimport {\n getDefaultColumnLabel,\n hasColumnFeature,\n hasTableFeature,\n} from '../../../utils';\n\nexport type DataTableSortColumnSelectProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n Select.TriggerProps,\n {\n /** A tabela. Exige `rowSortingFeature`. */\n table: TableWith<TFeatures, TData, 'rowSortingFeature'>;\n /**\n * O nome de uma coluna.\n * @default getDefaultColumnLabel: o `header` quando é texto, e o id quando não é\n */\n getLabel?: (column: Column<TFeatures, TData>) => string;\n /**\n * O nome da opção que tira a ordenação.\n * @default 'Sem ordenação'\n */\n noSortingLabel?: string;\n /**\n * O tamanho do select.\n * @default 'sm'\n */\n size?: Select.RootProps<string>['size'];\n }\n>;\n\n/** O valor da opção que tira a ordenação. Um id de coluna nunca é vazio. */\nconst NO_SORTING = '';\n\n/**\n * O select da coluna da ordenação, para onde o cabeçalho não serve de controle, como no celular.\n * Lista as colunas visíveis que ordenam, e \"Sem ordenação\" no topo; a coluna da ordenação atual\n * entra no fim mesmo escondida. Escolher uma coluna troca a\n * ordenação inteira por ela, na direção atual, ou na primeira da coluna sem ordenação antes. Com\n * a ordenação por várias colunas, mostra a primeira.\n *\n * Vai junto com o `DataTable.SortDirectionSelect`. Quando aparecem é do app, pela `className`\n * (ex.: `sm:hidden`). Renderiza o `Select` do `ui` por dentro; as props passam para o trigger.\n *\n * @example\n * ```tsx\n * <DataTable.SortColumnSelect table={table} className=\"sm:hidden\" />\n * <DataTable.SortDirectionSelect table={table} className=\"sm:hidden\" />\n * ```\n */\nexport const DataTableSortColumnSelect = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableSortColumnSelectProps<TFeatures, TData>,\n) => {\n const {\n table,\n getLabel = getDefaultColumnLabel,\n noSortingLabel = 'Sem ordenação',\n size = 'sm',\n disabled,\n ...rest\n } = props;\n\n /** Re-renderiza quando a primeira coluna da ordenação muda. */\n const sortedColumnId = useSelector(\n table.atoms.sorting,\n (sorting) => sorting[0]?.id ?? NO_SORTING,\n );\n\n /**\n * As colunas, que o TanStack memoiza: re-renderiza quando a ordem ou a visibilidade mudam. A\n * visibilidade é opcional, então assina o store.\n */\n const columns = useSelector(table.store, () =>\n hasTableFeature(table, 'columnVisibilityFeature')\n ? table.getVisibleLeafColumns()\n : table.getAllLeafColumns(),\n );\n\n const sortableColumns = columns.filter(\n (column) =>\n hasColumnFeature(column, 'rowSortingFeature') && column.getCanSort(),\n );\n\n /**\n * A coluna da ordenação entra no fim mesmo fora da lista: escondida, ou sem a ordenação pelo\n * usuário mas ordenada pelo código. Sem ela, o trigger mostraria o id.\n */\n const sortedColumn =\n sortedColumnId === NO_SORTING ||\n sortableColumns.some((column) => column.id === sortedColumnId)\n ? undefined\n : table.getColumn(sortedColumnId);\n\n const items = [\n { label: noSortingLabel, value: NO_SORTING },\n ...[...sortableColumns, ...(sortedColumn ? [sortedColumn] : [])].map(\n (column) => ({ label: getLabel(column), value: column.id }),\n ),\n ];\n\n const handleValueChange = (columnId: string | null) => {\n if (columnId === null || columnId === NO_SORTING) {\n table.resetSorting(true);\n\n return;\n }\n\n const column = table.getColumn(columnId);\n\n if (!(column && hasColumnFeature(column, 'rowSortingFeature'))) {\n return;\n }\n\n table.setSorting((sorting) => [\n {\n id: columnId,\n desc: sorting[0]?.desc ?? column.getFirstSortDir() === 'desc',\n },\n ]);\n };\n\n return (\n <Select.Root<string>\n size={size}\n value={sortedColumnId}\n items={items}\n disabled={disabled}\n onValueChange={handleValueChange}\n >\n <Select.Trigger\n data-component=\"DataTable.SortColumnSelect\"\n aria-label=\"Ordenar por\"\n {...rest}\n >\n <Select.Value />\n <Select.Icon />\n </Select.Trigger>\n\n <Select.Portal>\n <Select.Positioner alignItemWithTrigger={false}>\n <Select.Popup>\n <Select.List>\n {items.map((item) => (\n <Select.Item\n key={item.value}\n value={item.value}\n >\n <Select.ItemIndicator />\n <Select.ItemText>{item.label}</Select.ItemText>\n </Select.Item>\n ))}\n </Select.List>\n </Select.Popup>\n </Select.Positioner>\n </Select.Portal>\n </Select.Root>\n );\n};\n\nDataTableSortColumnSelect.displayName = 'DataTable.SortColumnSelect';\n"],"mappings":";;;;;;;AAsCA,MAAM,aAAa
|
|
1
|
+
{"version":3,"file":"data-table-sort-column-select.js","names":[],"sources":["../../../../src/components/data-table/toolbar/data-table-sort-column-select.tsx"],"sourcesContent":["import { Select } from '@lucasbernardosn/react-ui/collections/select';\nimport type { MergeOverride } from '@lucasbernardosn/utils';\nimport { useSelector } from '@tanstack/react-store';\nimport type { Column, RowData, TableFeatures } from '@tanstack/react-table';\nimport type { TableWith } from '../../../types';\nimport {\n getDefaultColumnLabel,\n hasColumnFeature,\n hasTableFeature,\n} from '../../../utils';\n\nexport type DataTableSortColumnSelectProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n Select.TriggerProps,\n {\n /** A tabela. Exige `rowSortingFeature`. */\n table: TableWith<TFeatures, TData, 'rowSortingFeature'>;\n /**\n * O nome de uma coluna.\n * @default getDefaultColumnLabel: o `header` quando é texto, e o id quando não é\n */\n getLabel?: (column: Column<TFeatures, TData>) => string;\n /**\n * O nome da opção que tira a ordenação.\n * @default 'Sem ordenação'\n */\n noSortingLabel?: string;\n /**\n * O tamanho do select.\n * @default 'sm'\n */\n size?: Select.RootProps<string>['size'];\n }\n>;\n\n/** O valor da opção que tira a ordenação. Um id de coluna nunca é vazio. */\nconst NO_SORTING = '';\n\n/**\n * O select da coluna da ordenação, para onde o cabeçalho não serve de controle, como no celular.\n * Lista as colunas visíveis que ordenam, e \"Sem ordenação\" no topo; a coluna da ordenação atual\n * entra no fim mesmo escondida. Com `enableSortingRemoval: false` na tabela, que deixa a lista\n * sempre ordenada, o \"Sem ordenação\" não aparece. Escolher uma coluna troca a\n * ordenação inteira por ela, na direção atual, ou na primeira da coluna sem ordenação antes. Com\n * a ordenação por várias colunas, mostra a primeira.\n *\n * Vai junto com o `DataTable.SortDirectionSelect`. Quando aparecem é do app, pela `className`\n * (ex.: `sm:hidden`). Renderiza o `Select` do `ui` por dentro; as props passam para o trigger.\n *\n * @example\n * ```tsx\n * <DataTable.SortColumnSelect table={table} className=\"sm:hidden\" />\n * <DataTable.SortDirectionSelect table={table} className=\"sm:hidden\" />\n * ```\n */\nexport const DataTableSortColumnSelect = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableSortColumnSelectProps<TFeatures, TData>,\n) => {\n const {\n table,\n getLabel = getDefaultColumnLabel,\n noSortingLabel = 'Sem ordenação',\n size = 'sm',\n disabled,\n ...rest\n } = props;\n\n /** Re-renderiza quando a primeira coluna da ordenação muda. */\n const sortedColumnId = useSelector(\n table.atoms.sorting,\n (sorting) => sorting[0]?.id ?? NO_SORTING,\n );\n\n /**\n * As colunas, que o TanStack memoiza: re-renderiza quando a ordem ou a visibilidade mudam. A\n * visibilidade é opcional, então assina o store.\n */\n const columns = useSelector(table.store, () =>\n hasTableFeature(table, 'columnVisibilityFeature')\n ? table.getVisibleLeafColumns()\n : table.getAllLeafColumns(),\n );\n\n const sortableColumns = columns.filter(\n (column) =>\n hasColumnFeature(column, 'rowSortingFeature') && column.getCanSort(),\n );\n\n /**\n * A coluna da ordenação entra no fim mesmo fora da lista: escondida, ou sem a ordenação pelo\n * usuário mas ordenada pelo código. Sem ela, o trigger mostraria o id.\n */\n const sortedColumn =\n sortedColumnId === NO_SORTING ||\n sortableColumns.some((column) => column.id === sortedColumnId)\n ? undefined\n : table.getColumn(sortedColumnId);\n\n const canRemoveSorting = table.options.enableSortingRemoval !== false;\n\n const items = [\n ...(canRemoveSorting ? [{ label: noSortingLabel, value: NO_SORTING }] : []),\n ...[...sortableColumns, ...(sortedColumn ? [sortedColumn] : [])].map(\n (column) => ({ label: getLabel(column), value: column.id }),\n ),\n ];\n\n const handleValueChange = (columnId: string | null) => {\n if (columnId === null || columnId === NO_SORTING) {\n table.resetSorting(true);\n\n return;\n }\n\n const column = table.getColumn(columnId);\n\n if (!(column && hasColumnFeature(column, 'rowSortingFeature'))) {\n return;\n }\n\n table.setSorting((sorting) => [\n {\n id: columnId,\n desc: sorting[0]?.desc ?? column.getFirstSortDir() === 'desc',\n },\n ]);\n };\n\n return (\n <Select.Root<string>\n size={size}\n value={sortedColumnId}\n items={items}\n disabled={disabled}\n onValueChange={handleValueChange}\n >\n <Select.Trigger\n data-component=\"DataTable.SortColumnSelect\"\n aria-label=\"Ordenar por\"\n {...rest}\n >\n <Select.Value />\n <Select.Icon />\n </Select.Trigger>\n\n <Select.Portal>\n <Select.Positioner alignItemWithTrigger={false}>\n <Select.Popup>\n <Select.List>\n {items.map((item) => (\n <Select.Item\n key={item.value}\n value={item.value}\n >\n <Select.ItemIndicator />\n <Select.ItemText>{item.label}</Select.ItemText>\n </Select.Item>\n ))}\n </Select.List>\n </Select.Popup>\n </Select.Positioner>\n </Select.Portal>\n </Select.Root>\n );\n};\n\nDataTableSortColumnSelect.displayName = 'DataTable.SortColumnSelect';\n"],"mappings":";;;;;;;AAsCA,MAAM,aAAa;;;;;;;;;;;;;;;;;;AAmBnB,MAAa,6BAIX,UACG;CACH,MAAM,EACJ,OACA,WAAW,uBACX,iBAAiB,iBACjB,OAAO,MACP,UACA,GAAG,SACD;;CAGJ,MAAM,iBAAiB,YACrB,MAAM,MAAM,UACX,YAAY,QAAQ,EAAE,EAAE,MAAM,UACjC;CAYA,MAAM,kBANU,YAAY,MAAM,aAChC,gBAAgB,OAAO,yBAAyB,IAC5C,MAAM,sBAAsB,IAC5B,MAAM,kBAAkB,CAGA,CAAC,CAAC,QAC7B,WACC,iBAAiB,QAAQ,mBAAmB,KAAK,OAAO,WAAW,CACvE;;;;;CAMA,MAAM,eACJ,mBAAmB,cACnB,gBAAgB,MAAM,WAAW,OAAO,OAAO,cAAc,IACzD,KAAA,IACA,MAAM,UAAU,cAAc;CAIpC,MAAM,QAAQ,CACZ,GAHuB,MAAM,QAAQ,yBAAyB,QAGvC,CAAC;EAAE,OAAO;EAAgB,OAAO;CAAW,CAAC,IAAI,CAAC,GACzE,GAAG,CAAC,GAAG,iBAAiB,GAAI,eAAe,CAAC,YAAY,IAAI,CAAC,CAAE,CAAC,CAAC,KAC9D,YAAY;EAAE,OAAO,SAAS,MAAM;EAAG,OAAO,OAAO;CAAG,EAC3D,CACF;CAEA,MAAM,qBAAqB,aAA4B;EACrD,IAAI,aAAa,QAAQ,aAAa,YAAY;GAChD,MAAM,aAAa,IAAI;GAEvB;EACF;EAEA,MAAM,SAAS,MAAM,UAAU,QAAQ;EAEvC,IAAI,EAAE,UAAU,iBAAiB,QAAQ,mBAAmB,IAC1D;EAGF,MAAM,YAAY,YAAY,CAC5B;GACE,IAAI;GACJ,MAAM,QAAQ,EAAE,EAAE,QAAQ,OAAO,gBAAgB,MAAM;EACzD,CACF,CAAC;CACH;CAEA,OACE,qBAAC,OAAO,MAAR;EACQ;EACN,OAAO;EACA;EACG;EACV,eAAe;EALjB,UAAA,CAOE,qBAAC,OAAO,SAAR;GACE,kBAAe;GACf,cAAW;GACX,GAAI;GAHN,UAAA,CAKE,oBAAC,OAAO,OAAR,CAAe,CAAA,GACf,oBAAC,OAAO,MAAR,CAAc,CAAA,CACA;EAEhB,CAAA,GAAA,oBAAC,OAAO,QAAR,EAAA,UACE,oBAAC,OAAO,YAAR;GAAmB,sBAAsB;GACvC,UAAA,oBAAC,OAAO,OAAR,EAAA,UACE,oBAAC,OAAO,MAAR,EAAA,UACG,MAAM,KAAK,SACV,qBAAC,OAAO,MAAR;IAEE,OAAO,KAAK;IAFd,UAAA,CAIE,oBAAC,OAAO,eAAR,CAAuB,CAAA,GACvB,oBAAC,OAAO,UAAR,EAAA,UAAkB,KAAK,MAAuB,CAAA,CACnC;GALN,GAAA,KAAK,KAKC,CACd,EACU,CAAA,EACD,CAAA;EACG,CAAA,EACN,CAAA,CACJ;;AAEjB;AAEA,0BAA0B,cAAc"}
|
|
@@ -18,7 +18,7 @@ import { TableFeature } from "@tanstack/react-table";
|
|
|
18
18
|
* initialState: { rowDensity: 'compact' },
|
|
19
19
|
* });
|
|
20
20
|
*
|
|
21
|
-
* table.setRowDensity('
|
|
21
|
+
* table.setRowDensity('airy');
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
24
|
export declare const rowDensityFeature: TableFeature;
|
|
@@ -22,7 +22,7 @@ const getInitialRowDensity = (initialState) => initialState.rowDensity ?? DEFAUL
|
|
|
22
22
|
* initialState: { rowDensity: 'compact' },
|
|
23
23
|
* });
|
|
24
24
|
*
|
|
25
|
-
* table.setRowDensity('
|
|
25
|
+
* table.setRowDensity('airy');
|
|
26
26
|
* ```
|
|
27
27
|
*/
|
|
28
28
|
const rowDensityFeature = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"row-density-feature.js","names":[],"sources":["../../../src/features/row-density/row-density-feature.ts"],"sourcesContent":["import {\n assignTableAPIs,\n makeStateUpdater,\n setStateSlice,\n type TableFeature,\n type TableState_All,\n type Updater,\n} from '@tanstack/react-table';\nimport type { RowDensity } from './row-density-feature.types';\n\n/** A densidade sem `initialState`. */\nconst DEFAULT_ROW_DENSITY: RowDensity = 'standard';\n\n/** A densidade de um estado inicial, ou a padrão quando ele não traz. */\nconst getInitialRowDensity = (initialState: Partial<TableState_All>) =>\n initialState.rowDensity ?? DEFAULT_ROW_DENSITY;\n\n/**\n * Feature do TanStack Table para a densidade das linhas. Registre com essa chave:\n * `tableFeatures({ rowDensityFeature })`.\n *\n * Só guarda o estado: o `DataTable.Root` o lê e marca o grid com `data-density`, de onde as\n * células tiram altura e espaçamento.\n *\n * @example\n * ```ts\n * const features = tableFeatures({ columnSizingFeature, rowDensityFeature });\n *\n * const table = useTable({\n * features,\n * columns,\n * data,\n * initialState: { rowDensity: 'compact' },\n * });\n *\n * table.setRowDensity('
|
|
1
|
+
{"version":3,"file":"row-density-feature.js","names":[],"sources":["../../../src/features/row-density/row-density-feature.ts"],"sourcesContent":["import {\n assignTableAPIs,\n makeStateUpdater,\n setStateSlice,\n type TableFeature,\n type TableState_All,\n type Updater,\n} from '@tanstack/react-table';\nimport type { RowDensity } from './row-density-feature.types';\n\n/** A densidade sem `initialState`. */\nconst DEFAULT_ROW_DENSITY: RowDensity = 'standard';\n\n/** A densidade de um estado inicial, ou a padrão quando ele não traz. */\nconst getInitialRowDensity = (initialState: Partial<TableState_All>) =>\n initialState.rowDensity ?? DEFAULT_ROW_DENSITY;\n\n/**\n * Feature do TanStack Table para a densidade das linhas. Registre com essa chave:\n * `tableFeatures({ rowDensityFeature })`.\n *\n * Só guarda o estado: o `DataTable.Root` o lê e marca o grid com `data-density`, de onde as\n * células tiram altura e espaçamento.\n *\n * @example\n * ```ts\n * const features = tableFeatures({ columnSizingFeature, rowDensityFeature });\n *\n * const table = useTable({\n * features,\n * columns,\n * data,\n * initialState: { rowDensity: 'compact' },\n * });\n *\n * table.setRowDensity('airy');\n * ```\n */\nexport const rowDensityFeature: TableFeature = {\n getInitialState: (initialState) => ({\n rowDensity: DEFAULT_ROW_DENSITY,\n ...initialState,\n }),\n\n getDefaultTableOptions: (table) => ({\n onRowDensityChange: makeStateUpdater('rowDensity', table),\n }),\n\n constructTableAPIs: (table) => {\n assignTableAPIs('rowDensityFeature', table, {\n table_setRowDensity: {\n fn: (updater: Updater<RowDensity>) =>\n setStateSlice(table, 'rowDensity', updater),\n },\n table_resetRowDensity: {\n fn: (defaultState?: boolean) =>\n setStateSlice(\n table,\n 'rowDensity',\n defaultState\n ? DEFAULT_ROW_DENSITY\n : getInitialRowDensity(table.initialState),\n ),\n },\n });\n },\n};\n"],"mappings":";;;AAWA,MAAM,sBAAkC;;AAGxC,MAAM,wBAAwB,iBAC5B,aAAa,cAAc;;;;;;;;;;;;;;;;;;;;;;AAuB7B,MAAa,oBAAkC;CAC7C,kBAAkB,kBAAkB;EAClC,YAAY;EACZ,GAAG;CACL;CAEA,yBAAyB,WAAW,EAClC,oBAAoB,iBAAiB,cAAc,KAAK,EAC1D;CAEA,qBAAqB,UAAU;EAC7B,gBAAgB,qBAAqB,OAAO;GAC1C,qBAAqB,EACnB,KAAK,YACH,cAAc,OAAO,cAAc,OAAO,EAC9C;GACA,uBAAuB,EACrB,KAAK,iBACH,cACE,OACA,cACA,eACI,sBACA,qBAAqB,MAAM,YAAY,CAC7C,EACJ;EACF,CAAC;CACH;AACF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { OnChangeFn, RowData, TableFeature, TableFeatures, Updater } from "@tanstack/react-table";
|
|
2
2
|
//#region src/features/row-density/row-density-feature.types.d.ts
|
|
3
3
|
/** A densidade das linhas: altura e espaçamento de células e headers. */
|
|
4
|
-
export type RowDensity = 'compact' | 'standard' | '
|
|
4
|
+
export type RowDensity = 'compact' | 'standard' | 'airy';
|
|
5
5
|
/** O estado da feature. */
|
|
6
6
|
export type TableState_RowDensity = {
|
|
7
7
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lucasbernardosn/react-table",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Composable data table parts on TanStack Table v9, styled with @lucasbernardosn/react-ui.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -27,15 +27,15 @@
|
|
|
27
27
|
"@dnd-kit/dom": "0.5.0",
|
|
28
28
|
"@dnd-kit/helpers": "0.5.0",
|
|
29
29
|
"@dnd-kit/react": "0.5.0",
|
|
30
|
-
"@lucasbernardosn/utils": "^0.
|
|
30
|
+
"@lucasbernardosn/utils": "^0.2.0",
|
|
31
31
|
"@phosphor-icons/react": "2.1.10",
|
|
32
32
|
"@tanstack/react-store": "0.11.2"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@biomejs/biome": "2.5.15",
|
|
36
|
-
"@lucasbernardosn/react-ui": "0.
|
|
37
|
-
"@lucasbernardosn/react-utils": "0.
|
|
38
|
-
"@lucasbernardosn/tsconfig": "
|
|
36
|
+
"@lucasbernardosn/react-ui": "0.2.0",
|
|
37
|
+
"@lucasbernardosn/react-utils": "0.2.0",
|
|
38
|
+
"@lucasbernardosn/tsconfig": "0.2.0",
|
|
39
39
|
"@tanstack/react-table": "9.2.4",
|
|
40
40
|
"@testing-library/jest-dom": "7.0.1",
|
|
41
41
|
"@testing-library/react": "16.3.3",
|
|
@@ -52,8 +52,8 @@
|
|
|
52
52
|
"vitest": "5.0.3"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
|
-
"@lucasbernardosn/react-ui": "^0.
|
|
56
|
-
"@lucasbernardosn/react-utils": "^0.
|
|
55
|
+
"@lucasbernardosn/react-ui": "^0.2.0",
|
|
56
|
+
"@lucasbernardosn/react-utils": "^0.2.0",
|
|
57
57
|
"@tanstack/react-table": "^9.2.4",
|
|
58
58
|
"react": "^19.0.0",
|
|
59
59
|
"react-dom": "^19.0.0"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"data-table-grid-classes.d.ts","names":[],"sources":["../../../../src/components/data-table/root/data-table-grid-classes.ts"],"mappings":";;;;;;;qBAMa"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"data-table-grid-classes.js","names":[],"sources":["../../../../src/components/data-table/root/data-table-grid-classes.ts"],"sourcesContent":["/**\n * A grade de uma linha, comum à `DataTable.Row`, à `DataTable.HeaderRow` e às linhas-fantasma do\n * `DataTable.Body`: o grid com o template das colunas, a linha vertical entre as células e a\n * horizontal embaixo. Num lugar só, para as três não divergirem; a regra da última linha fica em\n * cada uma.\n */\nexport const DATA_TABLE_GRID_CLASS_NAMES: string[] = [\n 'grid',\n 'grid-cols-(--data-table-template)',\n\n // Linha vertical entre as células: o `divide-x` põe borda no fim de cada filho, menos no\n // último, e assim a linha não tem borda na ponta direita. Fica na linha, e não na célula, para\n // a célula não precisar saber se é a última.\n 'divide-x',\n 'divide-gray-6',\n // Na fixada do fim, a linha vertical fica do lado do início, e a célula antes dela perde a do\n // fim: o centro rola por baixo e levaria a borda junto, e as duas somariam 2px quando encostam.\n '*:data-[pinned=end]:border-s',\n '*:data-[pinned=end]:border-gray-6',\n '*:has-[+[data-pinned=end]]:border-e-0',\n\n // Linha horizontal embaixo da linha.\n 'border-b',\n 'border-gray-6',\n];\n"],"mappings":";;;;;;;AAMA,MAAa,8BAAwC;CACnD;CACA;CAKA;CACA;CAGA;CACA;CACA;CAGA;CACA;AACF"}
|