@lucasbernardosn/react-table 0.2.0 → 0.4.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 +1 -1
- package/dist/components/column-menu/column-menu-hide-item.d.ts +1 -1
- package/dist/components/column-menu/column-menu-hide-item.js.map +1 -1
- package/dist/components/column-menu/column-menu-pin-items.d.ts +1 -1
- package/dist/components/column-menu/column-menu-pin-items.js.map +1 -1
- package/dist/components/column-menu/column-menu-popup.d.ts +1 -1
- package/dist/components/column-menu/column-menu-popup.js.map +1 -1
- package/dist/components/column-menu/column-menu-root.js.map +1 -1
- package/dist/components/column-menu/column-menu-sort-items.d.ts +1 -1
- package/dist/components/column-menu/column-menu-sort-items.js.map +1 -1
- package/dist/components/column-menu/column-menu-trigger.d.ts +1 -1
- package/dist/components/column-menu/column-menu-trigger.js.map +1 -1
- package/dist/components/columns-panel/columns-panel-item.d.ts +1 -1
- package/dist/components/columns-panel/columns-panel-item.js.map +1 -1
- package/dist/components/columns-panel/columns-panel-root.d.ts +1 -1
- package/dist/components/columns-panel/columns-panel-root.js.map +1 -1
- package/dist/components/data-table/body/data-table-body.d.ts +1 -1
- package/dist/components/data-table/body/data-table-body.js.map +1 -1
- package/dist/components/data-table/body/data-table-cell.d.ts +1 -1
- package/dist/components/data-table/body/data-table-cell.js.map +1 -1
- package/dist/components/data-table/body/data-table-empty.d.ts +1 -1
- package/dist/components/data-table/body/data-table-empty.js.map +1 -1
- package/dist/components/data-table/body/data-table-row.d.ts +1 -1
- package/dist/components/data-table/body/data-table-row.js.map +1 -1
- package/dist/components/data-table/header/data-table-header-cell.d.ts +1 -1
- package/dist/components/data-table/header/data-table-header-cell.js.map +1 -1
- package/dist/components/data-table/header/data-table-header-content.d.ts +1 -1
- package/dist/components/data-table/header/data-table-header-content.js.map +1 -1
- package/dist/components/data-table/header/data-table-header.d.ts +1 -1
- package/dist/components/data-table/header/data-table-header.js.map +1 -1
- package/dist/components/data-table/pagination/data-table-page-button.d.ts +1 -1
- package/dist/components/data-table/pagination/data-table-page-button.js.map +1 -1
- package/dist/components/data-table/pagination/data-table-page-size-select.d.ts +1 -1
- package/dist/components/data-table/pagination/data-table-page-size-select.js.map +1 -1
- package/dist/components/data-table/pagination/data-table-page-status.d.ts +1 -1
- package/dist/components/data-table/pagination/data-table-page-status.js.map +1 -1
- package/dist/components/data-table/pagination/data-table-pagination.d.ts +1 -1
- package/dist/components/data-table/pagination/data-table-pagination.js.map +1 -1
- package/dist/components/data-table/pagination/data-table-row-range.d.ts +1 -1
- package/dist/components/data-table/pagination/data-table-row-range.js.map +1 -1
- package/dist/components/data-table/pagination/data-table-selected-count.d.ts +1 -1
- package/dist/components/data-table/pagination/data-table-selected-count.js.map +1 -1
- package/dist/components/data-table/resize/data-table-resize-handle.d.ts +1 -1
- package/dist/components/data-table/resize/data-table-resize-handle.js.map +1 -1
- package/dist/components/data-table/root/data-table-root.d.ts +1 -1
- package/dist/components/data-table/root/data-table-root.js.map +1 -1
- package/dist/components/data-table/selection/data-table-row-checkbox.d.ts +1 -1
- package/dist/components/data-table/selection/data-table-row-checkbox.js.map +1 -1
- package/dist/components/data-table/selection/data-table-select-all-checkbox.d.ts +1 -1
- package/dist/components/data-table/selection/data-table-select-all-checkbox.js.map +1 -1
- package/dist/components/data-table/selection/data-table-selection-bar.d.ts +1 -1
- package/dist/components/data-table/selection/data-table-selection-bar.js.map +1 -1
- package/dist/components/data-table/sorting/data-table-sort-indicator.d.ts +1 -1
- package/dist/components/data-table/sorting/data-table-sort-indicator.js.map +1 -1
- package/dist/components/data-table/sorting/data-table-sort-trigger.d.ts +1 -1
- package/dist/components/data-table/sorting/data-table-sort-trigger.js.map +1 -1
- 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.map +1 -1
- package/dist/components/data-table/toolbar/data-table-sort-column-select.d.ts +1 -1
- package/dist/components/data-table/toolbar/data-table-sort-column-select.js.map +1 -1
- package/dist/components/data-table/toolbar/data-table-sort-direction-select.d.ts +1 -1
- package/dist/components/data-table/toolbar/data-table-sort-direction-select.js.map +1 -1
- package/package.json +12 -10
- package/dist/components/column-menu/column-menu-check.d.ts.map +0 -1
- package/dist/components/column-menu/column-menu-hide-item.d.ts.map +0 -1
- package/dist/components/column-menu/column-menu-labels.d.ts.map +0 -1
- package/dist/components/column-menu/column-menu-pin-items.d.ts.map +0 -1
- package/dist/components/column-menu/column-menu-popup.d.ts.map +0 -1
- package/dist/components/column-menu/column-menu-root.d.ts.map +0 -1
- package/dist/components/column-menu/column-menu-sort-items.d.ts.map +0 -1
- package/dist/components/column-menu/column-menu-trigger.d.ts.map +0 -1
- package/dist/components/column-menu/index.parts.d.ts.map +0 -1
- package/dist/components/columns-panel/columns-panel-item.d.ts.map +0 -1
- package/dist/components/columns-panel/columns-panel-root.d.ts.map +0 -1
- package/dist/components/columns-panel/get-columns-panel-column-order.d.ts.map +0 -1
- package/dist/components/columns-panel/index.parts.d.ts.map +0 -1
- package/dist/components/data-table/body/data-table-body.d.ts.map +0 -1
- package/dist/components/data-table/body/data-table-cell.d.ts.map +0 -1
- package/dist/components/data-table/body/data-table-empty.d.ts.map +0 -1
- package/dist/components/data-table/body/data-table-row-focus.d.ts.map +0 -1
- package/dist/components/data-table/body/data-table-row.d.ts.map +0 -1
- package/dist/components/data-table/body/use-data-table-row-focus-recovery.d.ts.map +0 -1
- package/dist/components/data-table/header/data-table-header-button.d.ts.map +0 -1
- package/dist/components/data-table/header/data-table-header-cell.d.ts.map +0 -1
- package/dist/components/data-table/header/data-table-header-content.d.ts.map +0 -1
- package/dist/components/data-table/header/data-table-header-row.d.ts.map +0 -1
- package/dist/components/data-table/header/data-table-header.d.ts.map +0 -1
- package/dist/components/data-table/index.parts.d.ts.map +0 -1
- package/dist/components/data-table/loading/get-data-table-loading-without-rows.d.ts.map +0 -1
- package/dist/components/data-table/loading/use-data-table-loading-inert.d.ts.map +0 -1
- package/dist/components/data-table/loading/use-data-table-loading.d.ts.map +0 -1
- package/dist/components/data-table/pagination/data-table-page-button.d.ts.map +0 -1
- package/dist/components/data-table/pagination/data-table-page-size-select.d.ts.map +0 -1
- package/dist/components/data-table/pagination/data-table-page-status.d.ts.map +0 -1
- package/dist/components/data-table/pagination/data-table-pagination.d.ts.map +0 -1
- package/dist/components/data-table/pagination/data-table-row-range.d.ts.map +0 -1
- package/dist/components/data-table/pagination/data-table-selected-count.d.ts.map +0 -1
- package/dist/components/data-table/pagination/use-data-table-page-scroll-reset.d.ts.map +0 -1
- package/dist/components/data-table/resize/data-table-resize-handle.d.ts.map +0 -1
- package/dist/components/data-table/resize/use-data-table-resize-scroll.d.ts.map +0 -1
- package/dist/components/data-table/root/data-table-grid-class-names.d.ts.map +0 -1
- package/dist/components/data-table/root/data-table-root.d.ts.map +0 -1
- package/dist/components/data-table/root/data-table-scroll-area.d.ts.map +0 -1
- package/dist/components/data-table/root/get-data-table-column-layout.d.ts.map +0 -1
- package/dist/components/data-table/root/get-data-table-column-pinning.d.ts.map +0 -1
- package/dist/components/data-table/root/get-data-table-scroll-parent.d.ts.map +0 -1
- package/dist/components/data-table/root/use-data-table-column-layout.d.ts.map +0 -1
- package/dist/components/data-table/root/use-data-table-header-offset.d.ts.map +0 -1
- package/dist/components/data-table/selection/data-table-row-checkbox.d.ts.map +0 -1
- package/dist/components/data-table/selection/data-table-select-all-checkbox.d.ts.map +0 -1
- package/dist/components/data-table/selection/data-table-selection-bar.d.ts.map +0 -1
- package/dist/components/data-table/selection/selection-column-def.d.ts.map +0 -1
- package/dist/components/data-table/sorting/data-table-sort-indicator.d.ts.map +0 -1
- package/dist/components/data-table/sorting/data-table-sort-trigger.d.ts.map +0 -1
- package/dist/components/data-table/toolbar/data-table-density-select.d.ts.map +0 -1
- package/dist/components/data-table/toolbar/data-table-sort-column-select.d.ts.map +0 -1
- package/dist/components/data-table/toolbar/data-table-sort-direction-select.d.ts.map +0 -1
- package/dist/features/active-row/active-row-feature.d.ts.map +0 -1
- package/dist/features/active-row/active-row-feature.types.d.ts.map +0 -1
- package/dist/features/column-alignment/column-alignment-feature.d.ts.map +0 -1
- package/dist/features/column-alignment/column-alignment-feature.types.d.ts.map +0 -1
- package/dist/features/loading/loading-feature.d.ts.map +0 -1
- package/dist/features/loading/loading-feature.types.d.ts.map +0 -1
- package/dist/features/row-density/row-density-feature.d.ts.map +0 -1
- package/dist/features/row-density/row-density-feature.types.d.ts.map +0 -1
- package/dist/types/table-with.d.ts.map +0 -1
- package/dist/utils/get-default-column-label.d.ts.map +0 -1
- package/dist/utils/has-feature.d.ts.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Header, RowData, TableFeatures } from "@tanstack/react-table";
|
|
2
2
|
import { useRender } from "@base-ui/react";
|
|
3
|
-
import { MergeOverride } from "@lucasbernardosn/utils";
|
|
3
|
+
import { MergeOverride } from "@lucasbernardosn/ts-utils";
|
|
4
4
|
//#region src/components/data-table/header/data-table-header-content.d.ts
|
|
5
5
|
export type DataTableHeaderContentProps<TFeatures extends TableFeatures, TData extends RowData> = MergeOverride<useRender.ComponentProps<'span'>, {
|
|
6
6
|
/** O header da coluna. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table-header-content.js","names":[],"sources":["../../../../src/components/data-table/header/data-table-header-content.tsx"],"sourcesContent":["import { mergeProps, useRender } from '@base-ui/react';\nimport { mergeTwClassNames } from '@lucasbernardosn/react-ui/utils';\nimport type { MergeOverride } from '@lucasbernardosn/utils';\nimport {\n FlexRender,\n type Header,\n type RowData,\n type TableFeatures,\n} from '@tanstack/react-table';\n\nexport type DataTableHeaderContentProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n useRender.ComponentProps<'span'>,\n {\n /** O header da coluna. */\n header: Header<TFeatures, TData>;\n }\n>;\n\n/**\n * O conteúdo do header: o `header` da definição da coluna, truncado com reticências. Num header\n * placeholder, fica vazio. Com `children`, eles substituem o da definição.\n *\n * Existe à parte porque o `DataTable.HeaderCell` não pode recortar: a área de agarre do\n * `DataTable.ResizeHandle` passa da borda dele, e conteúdo recortado não recebe clique.\n */\nexport const DataTableHeaderContent = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableHeaderContentProps<TFeatures, TData>,\n) => {\n const { header, render, className, children, ...rest } = props;\n\n const content = header.isPlaceholder ? null : <FlexRender header={header} />;\n\n const baseProps = {\n 'data-component': 'DataTable.HeaderContent',\n className: mergeTwClassNames(\n [\n // `span` em bloco: trunca como um bloco e ainda cabe num botão, que só aceita conteúdo\n // inline.\n 'block',\n 'min-w-0',\n 'truncate',\n\n // Afasta a borda do recorte 4px sem mover o conteúdo: cabe o anel de foco de um\n // controle aqui dentro, como o \"selecionar tudo\".\n '-m-1',\n 'p-1',\n ],\n className,\n ),\n children: children === undefined ? content : children,\n };\n\n return useRender({\n render,\n defaultTagName: 'span',\n props: mergeProps(baseProps, rest),\n });\n};\n\nDataTableHeaderContent.displayName = 'DataTable.HeaderContent';\n"],"mappings":";;;;;;;;;;;;AA4BA,MAAa,0BAIX,UACG;CACH,MAAM,EAAE,QAAQ,QAAQ,WAAW,UAAU,GAAG,SAAS;CAEzD,MAAM,UAAU,OAAO,gBAAgB,OAAO,oBAAC,YAAD,EAAoB,OAAS,CAAA;CAE3E,MAAM,YAAY;EAChB,kBAAkB;EAClB,WAAW,kBACT;GAGE;GACA;GACA;GAIA;GACA;EACF,GACA,SACF;EACA,UAAU,aAAa,KAAA,IAAY,UAAU;CAC/C;CAEA,OAAO,UAAU;EACf;EACA,gBAAgB;EAChB,OAAO,WAAW,WAAW,IAAI;CACnC,CAAC;AACH;AAEA,uBAAuB,cAAc"}
|
|
1
|
+
{"version":3,"file":"data-table-header-content.js","names":[],"sources":["../../../../src/components/data-table/header/data-table-header-content.tsx"],"sourcesContent":["import { mergeProps, useRender } from '@base-ui/react';\nimport { mergeTwClassNames } from '@lucasbernardosn/react-ui/utils';\nimport type { MergeOverride } from '@lucasbernardosn/ts-utils';\nimport {\n FlexRender,\n type Header,\n type RowData,\n type TableFeatures,\n} from '@tanstack/react-table';\n\nexport type DataTableHeaderContentProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n useRender.ComponentProps<'span'>,\n {\n /** O header da coluna. */\n header: Header<TFeatures, TData>;\n }\n>;\n\n/**\n * O conteúdo do header: o `header` da definição da coluna, truncado com reticências. Num header\n * placeholder, fica vazio. Com `children`, eles substituem o da definição.\n *\n * Existe à parte porque o `DataTable.HeaderCell` não pode recortar: a área de agarre do\n * `DataTable.ResizeHandle` passa da borda dele, e conteúdo recortado não recebe clique.\n */\nexport const DataTableHeaderContent = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableHeaderContentProps<TFeatures, TData>,\n) => {\n const { header, render, className, children, ...rest } = props;\n\n const content = header.isPlaceholder ? null : <FlexRender header={header} />;\n\n const baseProps = {\n 'data-component': 'DataTable.HeaderContent',\n className: mergeTwClassNames(\n [\n // `span` em bloco: trunca como um bloco e ainda cabe num botão, que só aceita conteúdo\n // inline.\n 'block',\n 'min-w-0',\n 'truncate',\n\n // Afasta a borda do recorte 4px sem mover o conteúdo: cabe o anel de foco de um\n // controle aqui dentro, como o \"selecionar tudo\".\n '-m-1',\n 'p-1',\n ],\n className,\n ),\n children: children === undefined ? content : children,\n };\n\n return useRender({\n render,\n defaultTagName: 'span',\n props: mergeProps(baseProps, rest),\n });\n};\n\nDataTableHeaderContent.displayName = 'DataTable.HeaderContent';\n"],"mappings":";;;;;;;;;;;;AA4BA,MAAa,0BAIX,UACG;CACH,MAAM,EAAE,QAAQ,QAAQ,WAAW,UAAU,GAAG,SAAS;CAEzD,MAAM,UAAU,OAAO,gBAAgB,OAAO,oBAAC,YAAD,EAAoB,OAAS,CAAA;CAE3E,MAAM,YAAY;EAChB,kBAAkB;EAClB,WAAW,kBACT;GAGE;GACA;GACA;GAIA;GACA;EACF,GACA,SACF;EACA,UAAU,aAAa,KAAA,IAAY,UAAU;CAC/C;CAEA,OAAO,UAAU;EACf;EACA,gBAAgB;EAChB,OAAO,WAAW,WAAW,IAAI;CACnC,CAAC;AACH;AAEA,uBAAuB,cAAc"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Header, RowData, Table, TableFeatures } from "@tanstack/react-table";
|
|
2
2
|
import { useRender } from "@base-ui/react";
|
|
3
3
|
import React from "react";
|
|
4
|
-
import { MergeOverride } from "@lucasbernardosn/utils";
|
|
4
|
+
import { MergeOverride } from "@lucasbernardosn/ts-utils";
|
|
5
5
|
//#region src/components/data-table/header/data-table-header.d.ts
|
|
6
6
|
export type DataTableHeaderProps<TFeatures extends TableFeatures, TData extends RowData> = MergeOverride<useRender.ComponentProps<'div'>, {
|
|
7
7
|
/** A tabela do `useTable`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table-header.js","names":["Fragment"],"sources":["../../../../src/components/data-table/header/data-table-header.tsx"],"sourcesContent":["import { mergeProps, useRender } from '@base-ui/react';\nimport { mergeTwClassNames } from '@lucasbernardosn/react-ui/utils';\nimport type { MergeOverride } from '@lucasbernardosn/utils';\nimport { shallow, useSelector } from '@tanstack/react-store';\nimport type {\n Header,\n RowData,\n Table,\n TableFeatures,\n} from '@tanstack/react-table';\nimport type React from 'react';\nimport { Fragment } from 'react';\nimport { hasTableFeature } from '../../../utils';\nimport { DataTableHeaderCell } from './data-table-header-cell';\nimport { DataTableHeaderRow } from './data-table-header-row';\n\nexport type DataTableHeaderProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n useRender.ComponentProps<'div'>,\n {\n /** A tabela do `useTable`. */\n table: Table<TFeatures, TData>;\n /**\n * Uma função que recebe cada header e devolve a célula dele: o `Header` monta uma\n * `DataTable.HeaderRow` por grupo de headers e chama a função para cada header. Com nós\n * comuns, quem usa faz o laço.\n * @default (header) => <DataTable.HeaderCell header={header} />\n */\n children?:\n | React.ReactNode\n | ((header: Header<TFeatures, TData>) => React.ReactNode);\n }\n>;\n\n/**\n * O cabeçalho da tabela (`role=\"rowgroup\"`), grudado no topo da área de rolagem.\n *\n * Com render-prop ou sem `children`, faz o laço sozinho: assina os grupos de headers e só\n * re-renderiza quando a estrutura das colunas muda (`columns`, ordem, visibilidade, pinning),\n * sem o dono da tabela precisar re-renderizar. Com nós comuns, o laço é de quem usa, e o dono\n * precisa re-renderizar quando a estrutura muda.\n *\n * Com `columnPinningFeature`, monta as linhas com os grupos de cada região (as fixadas no início,\n * o centro e as fixadas no fim): um grupo cujas colunas atravessam a fronteira da fixação vira um\n * header em cada região, e a parte fixada gruda.\n *\n * @example\n * ```tsx\n * <DataTable.Header table={table}>\n * {(header) => (\n * <DataTable.HeaderCell header={header}>\n * <DataTable.HeaderContent header={header} />\n * <DataTable.ResizeHandle header={header} />\n * </DataTable.HeaderCell>\n * )}\n * </DataTable.Header>\n * ```\n */\nexport const DataTableHeader = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableHeaderProps<TFeatures, TData>,\n) => {\n const { table, render, className, children, ...rest } = props;\n\n /**\n * Os grupos que o TanStack memoiza, numa tupla: o `shallow` compara item a item, e só\n * re-renderiza quando a estrutura das colunas muda. Tamanho, ordenação e seleção mudam o store,\n * mas não os grupos. Com pinning, os grupos de cada região: o de uma região só tem as colunas\n * dela.\n */\n const regionHeaderGroups = useSelector(\n table.store,\n () =>\n hasTableFeature(table, 'columnPinningFeature')\n ? [\n table.getStartHeaderGroups(),\n table.getCenterHeaderGroups(),\n table.getEndHeaderGroups(),\n ]\n : [table.getHeaderGroups()],\n { compare: shallow },\n );\n\n /**\n * As linhas do cabeçalho, uma por profundidade, com os headers das regiões na ordem do\n * template. Toda região tem o mesmo número de grupos, o da coluna mais funda.\n */\n const headerRows = (regionHeaderGroups[0] ?? []).map((headerGroup) => ({\n depth: headerGroup.depth,\n headers: regionHeaderGroups.flatMap(\n (headerGroups) => headerGroups[headerGroup.depth]?.headers ?? [],\n ),\n }));\n\n /**\n * Com render-prop ou sem `children`, o laço é daqui, com uma `HeaderRow` por grupo; com nós\n * comuns, de quem usa.\n */\n const content =\n typeof children === 'function' || children === undefined\n ? headerRows.map((headerRow) => (\n <DataTableHeaderRow key={headerRow.depth}>\n {headerRow.headers.map((header) => (\n <Fragment key={header.id}>\n {children === undefined ? (\n <DataTableHeaderCell header={header} />\n ) : (\n children(header)\n )}\n </Fragment>\n ))}\n </DataTableHeaderRow>\n ))\n : children;\n\n const baseProps = {\n 'data-component': 'DataTable.Header',\n role: 'rowgroup',\n className: mergeTwClassNames(\n [\n // Gruda no ancestral que rola, como o viewport do `DataTable.ScrollArea`.\n 'sticky',\n 'top-0',\n 'z-10',\n ],\n className,\n ),\n children: content,\n };\n\n return useRender({\n render,\n defaultTagName: 'div',\n props: mergeProps(baseProps, rest),\n });\n};\n\nDataTableHeader.displayName = 'DataTable.Header';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4DA,MAAa,mBAIX,UACG;CACH,MAAM,EAAE,OAAO,QAAQ,WAAW,UAAU,GAAG,SAAS;;;;;;;CAQxD,MAAM,qBAAqB,YACzB,MAAM,aAEJ,gBAAgB,OAAO,sBAAsB,IACzC;EACE,MAAM,qBAAqB;EAC3B,MAAM,sBAAsB;EAC5B,MAAM,mBAAmB;CAC3B,IACA,CAAC,MAAM,gBAAgB,CAAC,GAC9B,EAAE,SAAS,QAAQ,CACrB;;;;;CAMA,MAAM,cAAc,mBAAmB,MAAM,CAAC,EAAA,CAAG,KAAK,iBAAiB;EACrE,OAAO,YAAY;EACnB,SAAS,mBAAmB,SACzB,iBAAiB,aAAa,YAAY,MAAM,EAAE,WAAW,CAAC,CACjE;CACF,EAAE;;;;;CAMF,MAAM,UACJ,OAAO,aAAa,cAAc,aAAa,KAAA,IAC3C,WAAW,KAAK,cACd,oBAAC,oBAAD,EAAA,UACG,UAAU,QAAQ,KAAK,WACtB,oBAACA,YAAD,EAAA,UACG,aAAa,KAAA,IACZ,oBAAC,qBAAD,EAA6B,OAAS,CAAA,IAEtC,SAAS,MAAM,EAET,GANK,OAAO,EAMZ,CACX,EACiB,GAVK,UAAU,KAUf,CACrB,IACD;CAEN,MAAM,YAAY;EAChB,kBAAkB;EAClB,MAAM;EACN,WAAW,kBACT;GAEE;GACA;GACA;EACF,GACA,SACF;EACA,UAAU;CACZ;CAEA,OAAO,UAAU;EACf;EACA,gBAAgB;EAChB,OAAO,WAAW,WAAW,IAAI;CACnC,CAAC;AACH;AAEA,gBAAgB,cAAc"}
|
|
1
|
+
{"version":3,"file":"data-table-header.js","names":["Fragment"],"sources":["../../../../src/components/data-table/header/data-table-header.tsx"],"sourcesContent":["import { mergeProps, useRender } from '@base-ui/react';\nimport { mergeTwClassNames } from '@lucasbernardosn/react-ui/utils';\nimport type { MergeOverride } from '@lucasbernardosn/ts-utils';\nimport { shallow, useSelector } from '@tanstack/react-store';\nimport type {\n Header,\n RowData,\n Table,\n TableFeatures,\n} from '@tanstack/react-table';\nimport type React from 'react';\nimport { Fragment } from 'react';\nimport { hasTableFeature } from '../../../utils';\nimport { DataTableHeaderCell } from './data-table-header-cell';\nimport { DataTableHeaderRow } from './data-table-header-row';\n\nexport type DataTableHeaderProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n useRender.ComponentProps<'div'>,\n {\n /** A tabela do `useTable`. */\n table: Table<TFeatures, TData>;\n /**\n * Uma função que recebe cada header e devolve a célula dele: o `Header` monta uma\n * `DataTable.HeaderRow` por grupo de headers e chama a função para cada header. Com nós\n * comuns, quem usa faz o laço.\n * @default (header) => <DataTable.HeaderCell header={header} />\n */\n children?:\n | React.ReactNode\n | ((header: Header<TFeatures, TData>) => React.ReactNode);\n }\n>;\n\n/**\n * O cabeçalho da tabela (`role=\"rowgroup\"`), grudado no topo da área de rolagem.\n *\n * Com render-prop ou sem `children`, faz o laço sozinho: assina os grupos de headers e só\n * re-renderiza quando a estrutura das colunas muda (`columns`, ordem, visibilidade, pinning),\n * sem o dono da tabela precisar re-renderizar. Com nós comuns, o laço é de quem usa, e o dono\n * precisa re-renderizar quando a estrutura muda.\n *\n * Com `columnPinningFeature`, monta as linhas com os grupos de cada região (as fixadas no início,\n * o centro e as fixadas no fim): um grupo cujas colunas atravessam a fronteira da fixação vira um\n * header em cada região, e a parte fixada gruda.\n *\n * @example\n * ```tsx\n * <DataTable.Header table={table}>\n * {(header) => (\n * <DataTable.HeaderCell header={header}>\n * <DataTable.HeaderContent header={header} />\n * <DataTable.ResizeHandle header={header} />\n * </DataTable.HeaderCell>\n * )}\n * </DataTable.Header>\n * ```\n */\nexport const DataTableHeader = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableHeaderProps<TFeatures, TData>,\n) => {\n const { table, render, className, children, ...rest } = props;\n\n /**\n * Os grupos que o TanStack memoiza, numa tupla: o `shallow` compara item a item, e só\n * re-renderiza quando a estrutura das colunas muda. Tamanho, ordenação e seleção mudam o store,\n * mas não os grupos. Com pinning, os grupos de cada região: o de uma região só tem as colunas\n * dela.\n */\n const regionHeaderGroups = useSelector(\n table.store,\n () =>\n hasTableFeature(table, 'columnPinningFeature')\n ? [\n table.getStartHeaderGroups(),\n table.getCenterHeaderGroups(),\n table.getEndHeaderGroups(),\n ]\n : [table.getHeaderGroups()],\n { compare: shallow },\n );\n\n /**\n * As linhas do cabeçalho, uma por profundidade, com os headers das regiões na ordem do\n * template. Toda região tem o mesmo número de grupos, o da coluna mais funda.\n */\n const headerRows = (regionHeaderGroups[0] ?? []).map((headerGroup) => ({\n depth: headerGroup.depth,\n headers: regionHeaderGroups.flatMap(\n (headerGroups) => headerGroups[headerGroup.depth]?.headers ?? [],\n ),\n }));\n\n /**\n * Com render-prop ou sem `children`, o laço é daqui, com uma `HeaderRow` por grupo; com nós\n * comuns, de quem usa.\n */\n const content =\n typeof children === 'function' || children === undefined\n ? headerRows.map((headerRow) => (\n <DataTableHeaderRow key={headerRow.depth}>\n {headerRow.headers.map((header) => (\n <Fragment key={header.id}>\n {children === undefined ? (\n <DataTableHeaderCell header={header} />\n ) : (\n children(header)\n )}\n </Fragment>\n ))}\n </DataTableHeaderRow>\n ))\n : children;\n\n const baseProps = {\n 'data-component': 'DataTable.Header',\n role: 'rowgroup',\n className: mergeTwClassNames(\n [\n // Gruda no ancestral que rola, como o viewport do `DataTable.ScrollArea`.\n 'sticky',\n 'top-0',\n 'z-10',\n ],\n className,\n ),\n children: content,\n };\n\n return useRender({\n render,\n defaultTagName: 'div',\n props: mergeProps(baseProps, rest),\n });\n};\n\nDataTableHeader.displayName = 'DataTable.Header';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4DA,MAAa,mBAIX,UACG;CACH,MAAM,EAAE,OAAO,QAAQ,WAAW,UAAU,GAAG,SAAS;;;;;;;CAQxD,MAAM,qBAAqB,YACzB,MAAM,aAEJ,gBAAgB,OAAO,sBAAsB,IACzC;EACE,MAAM,qBAAqB;EAC3B,MAAM,sBAAsB;EAC5B,MAAM,mBAAmB;CAC3B,IACA,CAAC,MAAM,gBAAgB,CAAC,GAC9B,EAAE,SAAS,QAAQ,CACrB;;;;;CAMA,MAAM,cAAc,mBAAmB,MAAM,CAAC,EAAA,CAAG,KAAK,iBAAiB;EACrE,OAAO,YAAY;EACnB,SAAS,mBAAmB,SACzB,iBAAiB,aAAa,YAAY,MAAM,EAAE,WAAW,CAAC,CACjE;CACF,EAAE;;;;;CAMF,MAAM,UACJ,OAAO,aAAa,cAAc,aAAa,KAAA,IAC3C,WAAW,KAAK,cACd,oBAAC,oBAAD,EAAA,UACG,UAAU,QAAQ,KAAK,WACtB,oBAACA,YAAD,EAAA,UACG,aAAa,KAAA,IACZ,oBAAC,qBAAD,EAA6B,OAAS,CAAA,IAEtC,SAAS,MAAM,EAET,GANK,OAAO,EAMZ,CACX,EACiB,GAVK,UAAU,KAUf,CACrB,IACD;CAEN,MAAM,YAAY;EAChB,kBAAkB;EAClB,MAAM;EACN,WAAW,kBACT;GAEE;GACA;GACA;EACF,GACA,SACF;EACA,UAAU;CACZ;CAEA,OAAO,UAAU;EACf;EACA,gBAAgB;EAChB,OAAO,WAAW,WAAW,IAAI;CACnC,CAAC;AACH;AAEA,gBAAgB,cAAc"}
|
|
@@ -2,7 +2,7 @@ import { TableWith } from "../../../types/table-with.js";
|
|
|
2
2
|
import "../../../types/index.js";
|
|
3
3
|
import { RowData, TableFeatures } from "@tanstack/react-table";
|
|
4
4
|
import { IconButtonProps } from "@lucasbernardosn/react-ui/buttons/icon-button";
|
|
5
|
-
import { MergeOverride } from "@lucasbernardosn/utils";
|
|
5
|
+
import { MergeOverride } from "@lucasbernardosn/ts-utils";
|
|
6
6
|
//#region src/components/data-table/pagination/data-table-page-button.d.ts
|
|
7
7
|
/** Para onde o botão leva. */
|
|
8
8
|
export type DataTablePageButtonPage = 'first' | 'previous' | 'next' | 'last';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table-page-button.js","names":[],"sources":["../../../../src/components/data-table/pagination/data-table-page-button.tsx"],"sourcesContent":["import {\n IconButton,\n type IconButtonProps,\n} from '@lucasbernardosn/react-ui/buttons/icon-button';\nimport type { MergeOverride } from '@lucasbernardosn/utils';\nimport {\n CaretDoubleLeftIcon,\n CaretDoubleRightIcon,\n CaretLeftIcon,\n CaretRightIcon,\n} from '@phosphor-icons/react';\nimport { useSelector } from '@tanstack/react-store';\nimport type { RowData, TableFeatures } from '@tanstack/react-table';\nimport type { TableWith } from '../../../types';\n\n/** Para onde o botão leva. */\nexport type DataTablePageButtonPage = 'first' | 'previous' | 'next' | 'last';\n\nexport type DataTablePageButtonProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n Omit<IconButtonProps, 'icon' | 'aria-label'>,\n {\n /** A tabela. Exige `rowPaginationFeature`. */\n table: TableWith<TFeatures, TData, 'rowPaginationFeature'>;\n /** Para onde o botão leva: a primeira página, a anterior, a próxima ou a última. */\n page: DataTablePageButtonPage;\n /**\n * O ícone.\n * @default um caret por página: duplo nas pontas, simples na anterior e na próxima\n */\n icon?: IconButtonProps['icon'];\n /**\n * O que o botão faz.\n * @default 'Primeira página', 'Página anterior', 'Próxima página' ou 'Última página'\n */\n 'aria-label'?: string;\n }\n>;\n\nconst PAGE_LABELS: Record<DataTablePageButtonPage, string> = {\n first: 'Primeira página',\n previous: 'Página anterior',\n next: 'Próxima página',\n last: 'Última página',\n};\n\nconst PAGE_ICONS: Record<DataTablePageButtonPage, IconButtonProps['icon']> = {\n first: <CaretDoubleLeftIcon />,\n previous: <CaretLeftIcon />,\n next: <CaretRightIcon />,\n last: <CaretDoubleRightIcon />,\n};\n\n/**\n * O botão que leva a outra página: a primeira, a anterior, a próxima ou a última. Fica\n * desabilitado quando não há para onde ir. Sem o total de páginas (`pageCount: -1` na paginação\n * pela API), a próxima continua habilitada, e a última, não.\n *\n * As props do `IconButton` passam adiante, como `variant` e `size`.\n *\n * @example\n * ```tsx\n * <DataTable.PageButton\n * table={table}\n * page=\"next\"\n * />\n * ```\n */\nexport const DataTablePageButton = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTablePageButtonProps<TFeatures, TData>,\n) => {\n const { table, page, icon, onClick, ...rest } = props;\n\n /**\n * Re-renderiza quando o botão passa a ter ou deixa de ter para onde ir. O store, e não só o\n * atom da paginação: o total de páginas também muda com as linhas.\n */\n const isDisabled = useSelector(table.store, () => {\n if (page === 'first' || page === 'previous') {\n return !table.getCanPreviousPage();\n }\n\n return page === 'next' ? !table.getCanNextPage() : !table.getCanLastPage();\n });\n\n const goToPage = () => {\n if (page === 'first') {\n table.firstPage();\n } else if (page === 'previous') {\n table.previousPage();\n } else if (page === 'next') {\n table.nextPage();\n } else {\n table.lastPage();\n }\n };\n\n return (\n <IconButton\n data-component=\"DataTable.PageButton\"\n data-page={page}\n aria-label={PAGE_LABELS[page]}\n icon={icon ?? PAGE_ICONS[page]}\n variant=\"outline\"\n disabled={isDisabled}\n // O `onClick` do app roda antes, e um `preventDefault()` nele cancela a troca de página.\n onClick={(event) => {\n onClick?.(event);\n\n if (!event.defaultPrevented) {\n goToPage();\n }\n }}\n {...rest}\n />\n );\n};\n\nDataTablePageButton.displayName = 'DataTable.PageButton';\n"],"mappings":";;;;;AAyCA,MAAM,cAAuD;CAC3D,OAAO;CACP,UAAU;CACV,MAAM;CACN,MAAM;AACR;AAEA,MAAM,aAAuE;CAC3E,OAAO,oBAAC,qBAAD,CAAsB,CAAA;CAC7B,UAAU,oBAAC,eAAD,CAAgB,CAAA;CAC1B,MAAM,oBAAC,gBAAD,CAAiB,CAAA;CACvB,MAAM,oBAAC,sBAAD,CAAuB,CAAA;AAC/B;;;;;;;;;;;;;;;;AAiBA,MAAa,uBAIX,UACG;CACH,MAAM,EAAE,OAAO,MAAM,MAAM,SAAS,GAAG,SAAS;;;;;CAMhD,MAAM,aAAa,YAAY,MAAM,aAAa;EAChD,IAAI,SAAS,WAAW,SAAS,YAC/B,OAAO,CAAC,MAAM,mBAAmB;EAGnC,OAAO,SAAS,SAAS,CAAC,MAAM,eAAe,IAAI,CAAC,MAAM,eAAe;CAC3E,CAAC;CAED,MAAM,iBAAiB;EACrB,IAAI,SAAS,SACX,MAAM,UAAU;OACX,IAAI,SAAS,YAClB,MAAM,aAAa;OACd,IAAI,SAAS,QAClB,MAAM,SAAS;OAEf,MAAM,SAAS;CAEnB;CAEA,OACE,oBAAC,YAAD;EACE,kBAAe;EACf,aAAW;EACX,cAAY,YAAY;EACxB,MAAM,QAAQ,WAAW;EACzB,SAAQ;EACR,UAAU;EAEV,UAAU,UAAU;GAClB,UAAU,KAAK;GAEf,IAAI,CAAC,MAAM,kBACT,SAAS;EAEb;EACA,GAAI;CACL,CAAA;AAEL;AAEA,oBAAoB,cAAc"}
|
|
1
|
+
{"version":3,"file":"data-table-page-button.js","names":[],"sources":["../../../../src/components/data-table/pagination/data-table-page-button.tsx"],"sourcesContent":["import {\n IconButton,\n type IconButtonProps,\n} from '@lucasbernardosn/react-ui/buttons/icon-button';\nimport type { MergeOverride } from '@lucasbernardosn/ts-utils';\nimport {\n CaretDoubleLeftIcon,\n CaretDoubleRightIcon,\n CaretLeftIcon,\n CaretRightIcon,\n} from '@phosphor-icons/react';\nimport { useSelector } from '@tanstack/react-store';\nimport type { RowData, TableFeatures } from '@tanstack/react-table';\nimport type { TableWith } from '../../../types';\n\n/** Para onde o botão leva. */\nexport type DataTablePageButtonPage = 'first' | 'previous' | 'next' | 'last';\n\nexport type DataTablePageButtonProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n Omit<IconButtonProps, 'icon' | 'aria-label'>,\n {\n /** A tabela. Exige `rowPaginationFeature`. */\n table: TableWith<TFeatures, TData, 'rowPaginationFeature'>;\n /** Para onde o botão leva: a primeira página, a anterior, a próxima ou a última. */\n page: DataTablePageButtonPage;\n /**\n * O ícone.\n * @default um caret por página: duplo nas pontas, simples na anterior e na próxima\n */\n icon?: IconButtonProps['icon'];\n /**\n * O que o botão faz.\n * @default 'Primeira página', 'Página anterior', 'Próxima página' ou 'Última página'\n */\n 'aria-label'?: string;\n }\n>;\n\nconst PAGE_LABELS: Record<DataTablePageButtonPage, string> = {\n first: 'Primeira página',\n previous: 'Página anterior',\n next: 'Próxima página',\n last: 'Última página',\n};\n\nconst PAGE_ICONS: Record<DataTablePageButtonPage, IconButtonProps['icon']> = {\n first: <CaretDoubleLeftIcon />,\n previous: <CaretLeftIcon />,\n next: <CaretRightIcon />,\n last: <CaretDoubleRightIcon />,\n};\n\n/**\n * O botão que leva a outra página: a primeira, a anterior, a próxima ou a última. Fica\n * desabilitado quando não há para onde ir. Sem o total de páginas (`pageCount: -1` na paginação\n * pela API), a próxima continua habilitada, e a última, não.\n *\n * As props do `IconButton` passam adiante, como `variant` e `size`.\n *\n * @example\n * ```tsx\n * <DataTable.PageButton\n * table={table}\n * page=\"next\"\n * />\n * ```\n */\nexport const DataTablePageButton = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTablePageButtonProps<TFeatures, TData>,\n) => {\n const { table, page, icon, onClick, ...rest } = props;\n\n /**\n * Re-renderiza quando o botão passa a ter ou deixa de ter para onde ir. O store, e não só o\n * atom da paginação: o total de páginas também muda com as linhas.\n */\n const isDisabled = useSelector(table.store, () => {\n if (page === 'first' || page === 'previous') {\n return !table.getCanPreviousPage();\n }\n\n return page === 'next' ? !table.getCanNextPage() : !table.getCanLastPage();\n });\n\n const goToPage = () => {\n if (page === 'first') {\n table.firstPage();\n } else if (page === 'previous') {\n table.previousPage();\n } else if (page === 'next') {\n table.nextPage();\n } else {\n table.lastPage();\n }\n };\n\n return (\n <IconButton\n data-component=\"DataTable.PageButton\"\n data-page={page}\n aria-label={PAGE_LABELS[page]}\n icon={icon ?? PAGE_ICONS[page]}\n variant=\"outline\"\n disabled={isDisabled}\n // O `onClick` do app roda antes, e um `preventDefault()` nele cancela a troca de página.\n onClick={(event) => {\n onClick?.(event);\n\n if (!event.defaultPrevented) {\n goToPage();\n }\n }}\n {...rest}\n />\n );\n};\n\nDataTablePageButton.displayName = 'DataTable.PageButton';\n"],"mappings":";;;;;AAyCA,MAAM,cAAuD;CAC3D,OAAO;CACP,UAAU;CACV,MAAM;CACN,MAAM;AACR;AAEA,MAAM,aAAuE;CAC3E,OAAO,oBAAC,qBAAD,CAAsB,CAAA;CAC7B,UAAU,oBAAC,eAAD,CAAgB,CAAA;CAC1B,MAAM,oBAAC,gBAAD,CAAiB,CAAA;CACvB,MAAM,oBAAC,sBAAD,CAAuB,CAAA;AAC/B;;;;;;;;;;;;;;;;AAiBA,MAAa,uBAIX,UACG;CACH,MAAM,EAAE,OAAO,MAAM,MAAM,SAAS,GAAG,SAAS;;;;;CAMhD,MAAM,aAAa,YAAY,MAAM,aAAa;EAChD,IAAI,SAAS,WAAW,SAAS,YAC/B,OAAO,CAAC,MAAM,mBAAmB;EAGnC,OAAO,SAAS,SAAS,CAAC,MAAM,eAAe,IAAI,CAAC,MAAM,eAAe;CAC3E,CAAC;CAED,MAAM,iBAAiB;EACrB,IAAI,SAAS,SACX,MAAM,UAAU;OACX,IAAI,SAAS,YAClB,MAAM,aAAa;OACd,IAAI,SAAS,QAClB,MAAM,SAAS;OAEf,MAAM,SAAS;CAEnB;CAEA,OACE,oBAAC,YAAD;EACE,kBAAe;EACf,aAAW;EACX,cAAY,YAAY;EACxB,MAAM,QAAQ,WAAW;EACzB,SAAQ;EACR,UAAU;EAEV,UAAU,UAAU;GAClB,UAAU,KAAK;GAEf,IAAI,CAAC,MAAM,kBACT,SAAS;EAEb;EACA,GAAI;CACL,CAAA;AAEL;AAEA,oBAAoB,cAAc"}
|
|
@@ -3,7 +3,7 @@ import "../../../types/index.js";
|
|
|
3
3
|
import { RowData, TableFeatures } from "@tanstack/react-table";
|
|
4
4
|
import React from "react";
|
|
5
5
|
import { Select } from "@lucasbernardosn/react-ui/collections/select";
|
|
6
|
-
import { MergeOverride } from "@lucasbernardosn/utils";
|
|
6
|
+
import { MergeOverride } from "@lucasbernardosn/ts-utils";
|
|
7
7
|
//#region src/components/data-table/pagination/data-table-page-size-select.d.ts
|
|
8
8
|
export type DataTablePageSizeSelectProps<TFeatures extends TableFeatures, TData extends RowData> = MergeOverride<React.ComponentProps<'div'>, {
|
|
9
9
|
/** A tabela. Exige `rowPaginationFeature`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table-page-size-select.js","names":[],"sources":["../../../../src/components/data-table/pagination/data-table-page-size-select.tsx"],"sourcesContent":["import { Select } from '@lucasbernardosn/react-ui/collections/select';\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 React from 'react';\nimport type { TableWith } from '../../../types';\n\nexport type DataTablePageSizeSelectProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n React.ComponentProps<'div'>,\n {\n /** A tabela. Exige `rowPaginationFeature`. */\n table: TableWith<TFeatures, TData, 'rowPaginationFeature'>;\n /**\n * Os tamanhos oferecidos. O tamanho atual entra na lista mesmo fora dela.\n * @default [10, 25, 50, 100]\n */\n options?: readonly number[];\n /**\n * O rótulo do select.\n * @default 'Linhas por página'\n */\n label?: React.ReactNode;\n /**\n * O tamanho do select.\n * @default 'sm'\n */\n size?: Select.RootProps<number>['size'];\n }\n>;\n\nconst DEFAULT_PAGE_SIZE_OPTIONS = [10, 25, 50, 100];\n\n/**\n * O select de quantas linhas cada página mostra, com o rótulo ao lado. Trocar o tamanho chama o\n * `table.setPageSize`, que mantém à vista a primeira linha da página atual.\n *\n * Renderiza o `Select` do `ui` por dentro; as props passam para o elemento em volta do rótulo e do\n * trigger.\n *\n * @example\n * ```tsx\n * <DataTable.PageSizeSelect\n * table={table}\n * options={[20, 50, 100]}\n * />\n * ```\n */\nexport const DataTablePageSizeSelect = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTablePageSizeSelectProps<TFeatures, TData>,\n) => {\n const {\n table,\n options = DEFAULT_PAGE_SIZE_OPTIONS,\n label = 'Linhas por página',\n size = 'sm',\n className,\n ...rest\n } = props;\n\n /** Re-renderiza quando o tamanho da página muda. */\n const pageSize = useSelector(\n table.atoms.pagination,\n (pagination) => pagination.pageSize,\n );\n\n /** O tamanho atual entra na lista: sem ele, o trigger ficaria vazio. */\n const items = (options.includes(pageSize) ? options : [...options, pageSize])\n .toSorted((a, b) => a - b)\n .map((option) => ({\n label: option.toLocaleString('pt-BR'),\n value: option,\n }));\n\n return (\n <Select.Root<number>\n size={size}\n value={pageSize}\n items={items}\n onValueChange={(value) => {\n if (value !== null) {\n table.setPageSize(value);\n }\n }}\n >\n <div\n data-component=\"DataTable.PageSizeSelect\"\n className={mergeTwClassNames(\n ['flex', 'items-center', 'gap-2'],\n className,\n )}\n {...rest}\n >\n <Select.Label className=\"whitespace-nowrap font-normal text-gray-11\">\n {label}\n </Select.Label>\n\n <Select.Trigger>\n <Select.Value />\n <Select.Icon />\n </Select.Trigger>\n </div>\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\nDataTablePageSizeSelect.displayName = 'DataTable.PageSizeSelect';\n"],"mappings":";;;;;AAkCA,MAAM,4BAA4B;CAAC;CAAI;CAAI;CAAI;AAAG;;;;;;;;;;;;;;;;AAiBlD,MAAa,2BAIX,UACG;CACH,MAAM,EACJ,OACA,UAAU,2BACV,QAAQ,qBACR,OAAO,MACP,WACA,GAAG,SACD;;CAGJ,MAAM,WAAW,YACf,MAAM,MAAM,aACX,eAAe,WAAW,QAC7B;;CAGA,MAAM,SAAS,QAAQ,SAAS,QAAQ,IAAI,UAAU,CAAC,GAAG,SAAS,QAAQ,EAAA,CACxE,UAAU,GAAG,MAAM,IAAI,CAAC,CAAC,CACzB,KAAK,YAAY;EAChB,OAAO,OAAO,eAAe,OAAO;EACpC,OAAO;CACT,EAAE;CAEJ,OACE,qBAAC,OAAO,MAAR;EACQ;EACN,OAAO;EACA;EACP,gBAAgB,UAAU;GACxB,IAAI,UAAU,MACZ,MAAM,YAAY,KAAK;EAE3B;EARF,UAAA,CAUE,qBAAC,OAAD;GACE,kBAAe;GACf,WAAW,kBACT;IAAC;IAAQ;IAAgB;GAAO,GAChC,SACF;GACA,GAAI;GANN,UAAA,CAQE,oBAAC,OAAO,OAAR;IAAc,WAAU;IACrB,UAAA;GACW,CAAA,GAEd,qBAAC,OAAO,SAAR,EAAA,UAAA,CACE,oBAAC,OAAO,OAAR,CAAe,CAAA,GACf,oBAAC,OAAO,MAAR,CAAc,CAAA,CACA,EAAA,CAAA,CACb;EAEL,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,wBAAwB,cAAc"}
|
|
1
|
+
{"version":3,"file":"data-table-page-size-select.js","names":[],"sources":["../../../../src/components/data-table/pagination/data-table-page-size-select.tsx"],"sourcesContent":["import { Select } from '@lucasbernardosn/react-ui/collections/select';\nimport { mergeTwClassNames } from '@lucasbernardosn/react-ui/utils';\nimport type { MergeOverride } from '@lucasbernardosn/ts-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';\n\nexport type DataTablePageSizeSelectProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n React.ComponentProps<'div'>,\n {\n /** A tabela. Exige `rowPaginationFeature`. */\n table: TableWith<TFeatures, TData, 'rowPaginationFeature'>;\n /**\n * Os tamanhos oferecidos. O tamanho atual entra na lista mesmo fora dela.\n * @default [10, 25, 50, 100]\n */\n options?: readonly number[];\n /**\n * O rótulo do select.\n * @default 'Linhas por página'\n */\n label?: React.ReactNode;\n /**\n * O tamanho do select.\n * @default 'sm'\n */\n size?: Select.RootProps<number>['size'];\n }\n>;\n\nconst DEFAULT_PAGE_SIZE_OPTIONS = [10, 25, 50, 100];\n\n/**\n * O select de quantas linhas cada página mostra, com o rótulo ao lado. Trocar o tamanho chama o\n * `table.setPageSize`, que mantém à vista a primeira linha da página atual.\n *\n * Renderiza o `Select` do `ui` por dentro; as props passam para o elemento em volta do rótulo e do\n * trigger.\n *\n * @example\n * ```tsx\n * <DataTable.PageSizeSelect\n * table={table}\n * options={[20, 50, 100]}\n * />\n * ```\n */\nexport const DataTablePageSizeSelect = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTablePageSizeSelectProps<TFeatures, TData>,\n) => {\n const {\n table,\n options = DEFAULT_PAGE_SIZE_OPTIONS,\n label = 'Linhas por página',\n size = 'sm',\n className,\n ...rest\n } = props;\n\n /** Re-renderiza quando o tamanho da página muda. */\n const pageSize = useSelector(\n table.atoms.pagination,\n (pagination) => pagination.pageSize,\n );\n\n /** O tamanho atual entra na lista: sem ele, o trigger ficaria vazio. */\n const items = (options.includes(pageSize) ? options : [...options, pageSize])\n .toSorted((a, b) => a - b)\n .map((option) => ({\n label: option.toLocaleString('pt-BR'),\n value: option,\n }));\n\n return (\n <Select.Root<number>\n size={size}\n value={pageSize}\n items={items}\n onValueChange={(value) => {\n if (value !== null) {\n table.setPageSize(value);\n }\n }}\n >\n <div\n data-component=\"DataTable.PageSizeSelect\"\n className={mergeTwClassNames(\n ['flex', 'items-center', 'gap-2'],\n className,\n )}\n {...rest}\n >\n <Select.Label className=\"whitespace-nowrap font-normal text-gray-11\">\n {label}\n </Select.Label>\n\n <Select.Trigger>\n <Select.Value />\n <Select.Icon />\n </Select.Trigger>\n </div>\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\nDataTablePageSizeSelect.displayName = 'DataTable.PageSizeSelect';\n"],"mappings":";;;;;AAkCA,MAAM,4BAA4B;CAAC;CAAI;CAAI;CAAI;AAAG;;;;;;;;;;;;;;;;AAiBlD,MAAa,2BAIX,UACG;CACH,MAAM,EACJ,OACA,UAAU,2BACV,QAAQ,qBACR,OAAO,MACP,WACA,GAAG,SACD;;CAGJ,MAAM,WAAW,YACf,MAAM,MAAM,aACX,eAAe,WAAW,QAC7B;;CAGA,MAAM,SAAS,QAAQ,SAAS,QAAQ,IAAI,UAAU,CAAC,GAAG,SAAS,QAAQ,EAAA,CACxE,UAAU,GAAG,MAAM,IAAI,CAAC,CAAC,CACzB,KAAK,YAAY;EAChB,OAAO,OAAO,eAAe,OAAO;EACpC,OAAO;CACT,EAAE;CAEJ,OACE,qBAAC,OAAO,MAAR;EACQ;EACN,OAAO;EACA;EACP,gBAAgB,UAAU;GACxB,IAAI,UAAU,MACZ,MAAM,YAAY,KAAK;EAE3B;EARF,UAAA,CAUE,qBAAC,OAAD;GACE,kBAAe;GACf,WAAW,kBACT;IAAC;IAAQ;IAAgB;GAAO,GAChC,SACF;GACA,GAAI;GANN,UAAA,CAQE,oBAAC,OAAO,OAAR;IAAc,WAAU;IACrB,UAAA;GACW,CAAA,GAEd,qBAAC,OAAO,SAAR,EAAA,UAAA,CACE,oBAAC,OAAO,OAAR,CAAe,CAAA,GACf,oBAAC,OAAO,MAAR,CAAc,CAAA,CACA,EAAA,CAAA,CACb;EAEL,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,wBAAwB,cAAc"}
|
|
@@ -3,7 +3,7 @@ import "../../../types/index.js";
|
|
|
3
3
|
import { RowData, TableFeatures } from "@tanstack/react-table";
|
|
4
4
|
import { useRender } from "@base-ui/react";
|
|
5
5
|
import React from "react";
|
|
6
|
-
import { MergeOverride } from "@lucasbernardosn/utils";
|
|
6
|
+
import { MergeOverride } from "@lucasbernardosn/ts-utils";
|
|
7
7
|
//#region src/components/data-table/pagination/data-table-page-status.d.ts
|
|
8
8
|
/** A página atual e o total, para o texto do `DataTable.PageStatus`. */
|
|
9
9
|
export type DataTablePageStatusValues = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table-page-status.js","names":[],"sources":["../../../../src/components/data-table/pagination/data-table-page-status.tsx"],"sourcesContent":["import { mergeProps, useRender } from '@base-ui/react';\nimport { mergeTwClassNames } from '@lucasbernardosn/react-ui/utils';\nimport type { MergeOverride } from '@lucasbernardosn/utils';\nimport { shallow, useSelector } from '@tanstack/react-store';\nimport type { RowData, TableFeatures } from '@tanstack/react-table';\nimport type React from 'react';\nimport type { TableWith } from '../../../types';\nimport { getDataTableLoadingWithoutRows } from '../loading/get-data-table-loading-without-rows';\n\n/** A página atual e o total, para o texto do `DataTable.PageStatus`. */\nexport type DataTablePageStatusValues = {\n /** O índice da página atual, a partir de 0. */\n pageIndex: number;\n /**\n * O total de páginas, ou `-1` sem ele: quando a API não informa (`pageCount: -1`) e, com\n * `loadingFeature`, na carga sem linhas, antes de o total chegar.\n */\n pageCount: number;\n};\n\nexport type DataTablePageStatusProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n useRender.ComponentProps<'span'>,\n {\n /** A tabela. Exige `rowPaginationFeature`. */\n table: TableWith<TFeatures, TData, 'rowPaginationFeature'>;\n /**\n * Uma função que recebe a página e o total e devolve o texto.\n * @default ({ pageIndex, pageCount }) => 'Página 2 de 10', ou 'Página 2' sem o total\n */\n children?: (values: DataTablePageStatusValues) => React.ReactNode;\n }\n>;\n\n/**\n * Qual a página atual, e de quantas: \"Página 2 de 10\". Sem o total de páginas, só \"Página 2\",\n * também na primeira carga, quando o total ainda não chegou.\n *\n * @example\n * ```tsx\n * <DataTable.PageStatus table={table}>\n * {({ pageIndex, pageCount }) => `${pageIndex + 1}/${pageCount}`}\n * </DataTable.PageStatus>\n * ```\n */\nexport const DataTablePageStatus = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTablePageStatusProps<TFeatures, TData>,\n) => {\n const { table, render, className, children, ...rest } = props;\n\n /**\n * Re-renderiza quando a página ou o total mudam. O store, e não só o atom da paginação: o total\n * também muda com as linhas.\n */\n const values = useSelector(\n table.store,\n (): DataTablePageStatusValues => ({\n pageIndex: table.atoms.pagination.get().pageIndex,\n pageCount: getDataTableLoadingWithoutRows(table)\n ? -1\n : table.getPageCount(),\n }),\n { compare: shallow },\n );\n\n const page = (values.pageIndex + 1).toLocaleString('pt-BR');\n\n const baseProps = {\n 'data-component': 'DataTable.PageStatus',\n className: mergeTwClassNames(\n ['text-gray-11', 'text-sm', 'tabular-nums', 'whitespace-nowrap'],\n className,\n ),\n children:\n children === undefined\n ? values.pageCount === -1\n ? `Página ${page}`\n : // Sem linhas, o total é 0, e a página 1 continua sendo a atual.\n `Página ${page} de ${Math.max(values.pageCount, 1).toLocaleString('pt-BR')}`\n : children(values),\n };\n\n return useRender({\n render,\n defaultTagName: 'span',\n props: mergeProps(baseProps, rest),\n });\n};\n\nDataTablePageStatus.displayName = 'DataTable.PageStatus';\n"],"mappings":";;;;;;;;;;;;;;;;AA+CA,MAAa,uBAIX,UACG;CACH,MAAM,EAAE,OAAO,QAAQ,WAAW,UAAU,GAAG,SAAS;;;;;CAMxD,MAAM,SAAS,YACb,MAAM,cAC4B;EAChC,WAAW,MAAM,MAAM,WAAW,IAAI,CAAC,CAAC;EACxC,WAAW,+BAA+B,KAAK,IAC3C,KACA,MAAM,aAAa;CACzB,IACA,EAAE,SAAS,QAAQ,CACrB;CAEA,MAAM,QAAQ,OAAO,YAAY,EAAA,CAAG,eAAe,OAAO;CAE1D,MAAM,YAAY;EAChB,kBAAkB;EAClB,WAAW,kBACT;GAAC;GAAgB;GAAW;GAAgB;EAAmB,GAC/D,SACF;EACA,UACE,aAAa,KAAA,IACT,OAAO,cAAc,KACnB,UAAU,SAEV,UAAU,KAAK,MAAM,KAAK,IAAI,OAAO,WAAW,CAAC,CAAC,CAAC,eAAe,OAAO,MAC3E,SAAS,MAAM;CACvB;CAEA,OAAO,UAAU;EACf;EACA,gBAAgB;EAChB,OAAO,WAAW,WAAW,IAAI;CACnC,CAAC;AACH;AAEA,oBAAoB,cAAc"}
|
|
1
|
+
{"version":3,"file":"data-table-page-status.js","names":[],"sources":["../../../../src/components/data-table/pagination/data-table-page-status.tsx"],"sourcesContent":["import { mergeProps, useRender } from '@base-ui/react';\nimport { mergeTwClassNames } from '@lucasbernardosn/react-ui/utils';\nimport type { MergeOverride } from '@lucasbernardosn/ts-utils';\nimport { shallow, useSelector } from '@tanstack/react-store';\nimport type { RowData, TableFeatures } from '@tanstack/react-table';\nimport type React from 'react';\nimport type { TableWith } from '../../../types';\nimport { getDataTableLoadingWithoutRows } from '../loading/get-data-table-loading-without-rows';\n\n/** A página atual e o total, para o texto do `DataTable.PageStatus`. */\nexport type DataTablePageStatusValues = {\n /** O índice da página atual, a partir de 0. */\n pageIndex: number;\n /**\n * O total de páginas, ou `-1` sem ele: quando a API não informa (`pageCount: -1`) e, com\n * `loadingFeature`, na carga sem linhas, antes de o total chegar.\n */\n pageCount: number;\n};\n\nexport type DataTablePageStatusProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n useRender.ComponentProps<'span'>,\n {\n /** A tabela. Exige `rowPaginationFeature`. */\n table: TableWith<TFeatures, TData, 'rowPaginationFeature'>;\n /**\n * Uma função que recebe a página e o total e devolve o texto.\n * @default ({ pageIndex, pageCount }) => 'Página 2 de 10', ou 'Página 2' sem o total\n */\n children?: (values: DataTablePageStatusValues) => React.ReactNode;\n }\n>;\n\n/**\n * Qual a página atual, e de quantas: \"Página 2 de 10\". Sem o total de páginas, só \"Página 2\",\n * também na primeira carga, quando o total ainda não chegou.\n *\n * @example\n * ```tsx\n * <DataTable.PageStatus table={table}>\n * {({ pageIndex, pageCount }) => `${pageIndex + 1}/${pageCount}`}\n * </DataTable.PageStatus>\n * ```\n */\nexport const DataTablePageStatus = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTablePageStatusProps<TFeatures, TData>,\n) => {\n const { table, render, className, children, ...rest } = props;\n\n /**\n * Re-renderiza quando a página ou o total mudam. O store, e não só o atom da paginação: o total\n * também muda com as linhas.\n */\n const values = useSelector(\n table.store,\n (): DataTablePageStatusValues => ({\n pageIndex: table.atoms.pagination.get().pageIndex,\n pageCount: getDataTableLoadingWithoutRows(table)\n ? -1\n : table.getPageCount(),\n }),\n { compare: shallow },\n );\n\n const page = (values.pageIndex + 1).toLocaleString('pt-BR');\n\n const baseProps = {\n 'data-component': 'DataTable.PageStatus',\n className: mergeTwClassNames(\n ['text-gray-11', 'text-sm', 'tabular-nums', 'whitespace-nowrap'],\n className,\n ),\n children:\n children === undefined\n ? values.pageCount === -1\n ? `Página ${page}`\n : // Sem linhas, o total é 0, e a página 1 continua sendo a atual.\n `Página ${page} de ${Math.max(values.pageCount, 1).toLocaleString('pt-BR')}`\n : children(values),\n };\n\n return useRender({\n render,\n defaultTagName: 'span',\n props: mergeProps(baseProps, rest),\n });\n};\n\nDataTablePageStatus.displayName = 'DataTable.PageStatus';\n"],"mappings":";;;;;;;;;;;;;;;;AA+CA,MAAa,uBAIX,UACG;CACH,MAAM,EAAE,OAAO,QAAQ,WAAW,UAAU,GAAG,SAAS;;;;;CAMxD,MAAM,SAAS,YACb,MAAM,cAC4B;EAChC,WAAW,MAAM,MAAM,WAAW,IAAI,CAAC,CAAC;EACxC,WAAW,+BAA+B,KAAK,IAC3C,KACA,MAAM,aAAa;CACzB,IACA,EAAE,SAAS,QAAQ,CACrB;CAEA,MAAM,QAAQ,OAAO,YAAY,EAAA,CAAG,eAAe,OAAO;CAE1D,MAAM,YAAY;EAChB,kBAAkB;EAClB,WAAW,kBACT;GAAC;GAAgB;GAAW;GAAgB;EAAmB,GAC/D,SACF;EACA,UACE,aAAa,KAAA,IACT,OAAO,cAAc,KACnB,UAAU,SAEV,UAAU,KAAK,MAAM,KAAK,IAAI,OAAO,WAAW,CAAC,CAAC,CAAC,eAAe,OAAO,MAC3E,SAAS,MAAM;CACvB;CAEA,OAAO,UAAU;EACf;EACA,gBAAgB;EAChB,OAAO,WAAW,WAAW,IAAI;CACnC,CAAC;AACH;AAEA,oBAAoB,cAAc"}
|
|
@@ -2,7 +2,7 @@ import { TableWith } from "../../../types/table-with.js";
|
|
|
2
2
|
import "../../../types/index.js";
|
|
3
3
|
import { RowData, TableFeatures } from "@tanstack/react-table";
|
|
4
4
|
import { useRender } from "@base-ui/react";
|
|
5
|
-
import { MergeOverride } from "@lucasbernardosn/utils";
|
|
5
|
+
import { MergeOverride } from "@lucasbernardosn/ts-utils";
|
|
6
6
|
//#region src/components/data-table/pagination/data-table-pagination.d.ts
|
|
7
7
|
export type DataTablePaginationProps<TFeatures extends TableFeatures, TData extends RowData> = MergeOverride<useRender.ComponentProps<'nav'>, {
|
|
8
8
|
/** A tabela. Exige `rowPaginationFeature`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table-pagination.js","names":[],"sources":["../../../../src/components/data-table/pagination/data-table-pagination.tsx"],"sourcesContent":["import { mergeProps, useRender } from '@base-ui/react';\nimport { mergeTwClassNames } from '@lucasbernardosn/react-ui/utils';\nimport type { MergeOverride } from '@lucasbernardosn/utils';\nimport type { RowData, TableFeatures } from '@tanstack/react-table';\nimport type { TableWith } from '../../../types';\nimport { hasTableFeature } from '../../../utils';\nimport { DataTablePageButton } from './data-table-page-button';\nimport { DataTablePageSizeSelect } from './data-table-page-size-select';\nimport { DataTablePageStatus } from './data-table-page-status';\nimport { DataTableRowRange } from './data-table-row-range';\nimport { DataTableSelectedCount } from './data-table-selected-count';\n\nexport type DataTablePaginationProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n useRender.ComponentProps<'nav'>,\n {\n /** A tabela. Exige `rowPaginationFeature`. */\n table: TableWith<TFeatures, TData, 'rowPaginationFeature'>;\n }\n>;\n\n/**\n * A barra da paginação, para baixo da tabela. Sem `children`, monta o padrão: à esquerda, a\n * contagem de selecionadas (com `rowSelectionFeature`); à direita, o `DataTable.PageSizeSelect`,\n * o `DataTable.RowRange`, o `DataTable.PageStatus` e os quatro `DataTable.PageButton`. Com\n * `children`, o app compõe as partes, cada uma com a `table`. Em tela estreita, os grupos quebram\n * linha.\n *\n * Funciona com a paginação local (`createPaginatedRowModel`) e com a da API\n * (`manualPagination`, com o `rowCount` ou o `pageCount`).\n *\n * É um `nav` com o nome \"Paginação\", trocável pelo `aria-label`: um marco, que o leitor de tela\n * lista e para onde salta.\n *\n * @example\n * ```tsx\n * <DataTable.Pagination table={table}>\n * <DataTable.PageStatus table={table} />\n * <DataTable.PageButton table={table} page=\"previous\" />\n * <DataTable.PageButton table={table} page=\"next\" />\n * </DataTable.Pagination>\n * ```\n */\nexport const DataTablePagination = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTablePaginationProps<TFeatures, TData>,\n) => {\n const { table, render, className, children, ...rest } = props;\n\n const content =\n children === undefined ? (\n <>\n {hasTableFeature(table, 'rowSelectionFeature') && (\n <DataTableSelectedCount table={table} />\n )}\n\n {/* À direita mesmo sozinho, sem a contagem: o `justify-between` o levaria para a\n esquerda. */}\n <div className=\"ms-auto flex flex-wrap items-center gap-x-4 gap-y-2\">\n <DataTablePageSizeSelect table={table} />\n <DataTableRowRange table={table} />\n <DataTablePageStatus table={table} />\n\n <div className=\"flex items-center gap-1\">\n <DataTablePageButton\n table={table}\n page=\"first\"\n />\n <DataTablePageButton\n table={table}\n page=\"previous\"\n />\n <DataTablePageButton\n table={table}\n page=\"next\"\n />\n <DataTablePageButton\n table={table}\n page=\"last\"\n />\n </div>\n </div>\n </>\n ) : (\n children\n );\n\n const baseProps = {\n 'data-component': 'DataTable.Pagination',\n 'aria-label': 'Paginação',\n className: mergeTwClassNames(\n [\n 'flex',\n 'flex-wrap',\n 'items-center',\n 'justify-between',\n 'gap-x-6',\n 'gap-y-2',\n ],\n className,\n ),\n children: content,\n };\n\n return useRender({\n render,\n defaultTagName: 'nav',\n props: mergeProps(baseProps, rest),\n });\n};\n\nDataTablePagination.displayName = 'DataTable.Pagination';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CA,MAAa,uBAIX,UACG;CACH,MAAM,EAAE,OAAO,QAAQ,WAAW,UAAU,GAAG,SAAS;CAExD,MAAM,UACJ,aAAa,KAAA,IACX,qBAAA,UAAA,EAAA,UAAA,CACG,gBAAgB,OAAO,qBAAqB,KAC3C,oBAAC,wBAAD,EAA+B,MAAQ,CAAA,GAKzC,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA;GACE,oBAAC,yBAAD,EAAgC,MAAQ,CAAA;GACxC,oBAAC,mBAAD,EAA0B,MAAQ,CAAA;GAClC,oBAAC,qBAAD,EAA4B,MAAQ,CAAA;GAEpC,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA;KACE,oBAAC,qBAAD;MACS;MACP,MAAK;KACN,CAAA;KACD,oBAAC,qBAAD;MACS;MACP,MAAK;KACN,CAAA;KACD,oBAAC,qBAAD;MACS;MACP,MAAK;KACN,CAAA;KACD,oBAAC,qBAAD;MACS;MACP,MAAK;KACN,CAAA;IACE;;EACF;CACL,CAAA,CAAA,EAAA,CAAA,IAEF;CAGJ,MAAM,YAAY;EAChB,kBAAkB;EAClB,cAAc;EACd,WAAW,kBACT;GACE;GACA;GACA;GACA;GACA;GACA;EACF,GACA,SACF;EACA,UAAU;CACZ;CAEA,OAAO,UAAU;EACf;EACA,gBAAgB;EAChB,OAAO,WAAW,WAAW,IAAI;CACnC,CAAC;AACH;AAEA,oBAAoB,cAAc"}
|
|
1
|
+
{"version":3,"file":"data-table-pagination.js","names":[],"sources":["../../../../src/components/data-table/pagination/data-table-pagination.tsx"],"sourcesContent":["import { mergeProps, useRender } from '@base-ui/react';\nimport { mergeTwClassNames } from '@lucasbernardosn/react-ui/utils';\nimport type { MergeOverride } from '@lucasbernardosn/ts-utils';\nimport type { RowData, TableFeatures } from '@tanstack/react-table';\nimport type { TableWith } from '../../../types';\nimport { hasTableFeature } from '../../../utils';\nimport { DataTablePageButton } from './data-table-page-button';\nimport { DataTablePageSizeSelect } from './data-table-page-size-select';\nimport { DataTablePageStatus } from './data-table-page-status';\nimport { DataTableRowRange } from './data-table-row-range';\nimport { DataTableSelectedCount } from './data-table-selected-count';\n\nexport type DataTablePaginationProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n useRender.ComponentProps<'nav'>,\n {\n /** A tabela. Exige `rowPaginationFeature`. */\n table: TableWith<TFeatures, TData, 'rowPaginationFeature'>;\n }\n>;\n\n/**\n * A barra da paginação, para baixo da tabela. Sem `children`, monta o padrão: à esquerda, a\n * contagem de selecionadas (com `rowSelectionFeature`); à direita, o `DataTable.PageSizeSelect`,\n * o `DataTable.RowRange`, o `DataTable.PageStatus` e os quatro `DataTable.PageButton`. Com\n * `children`, o app compõe as partes, cada uma com a `table`. Em tela estreita, os grupos quebram\n * linha.\n *\n * Funciona com a paginação local (`createPaginatedRowModel`) e com a da API\n * (`manualPagination`, com o `rowCount` ou o `pageCount`).\n *\n * É um `nav` com o nome \"Paginação\", trocável pelo `aria-label`: um marco, que o leitor de tela\n * lista e para onde salta.\n *\n * @example\n * ```tsx\n * <DataTable.Pagination table={table}>\n * <DataTable.PageStatus table={table} />\n * <DataTable.PageButton table={table} page=\"previous\" />\n * <DataTable.PageButton table={table} page=\"next\" />\n * </DataTable.Pagination>\n * ```\n */\nexport const DataTablePagination = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTablePaginationProps<TFeatures, TData>,\n) => {\n const { table, render, className, children, ...rest } = props;\n\n const content =\n children === undefined ? (\n <>\n {hasTableFeature(table, 'rowSelectionFeature') && (\n <DataTableSelectedCount table={table} />\n )}\n\n {/* À direita mesmo sozinho, sem a contagem: o `justify-between` o levaria para a\n esquerda. */}\n <div className=\"ms-auto flex flex-wrap items-center gap-x-4 gap-y-2\">\n <DataTablePageSizeSelect table={table} />\n <DataTableRowRange table={table} />\n <DataTablePageStatus table={table} />\n\n <div className=\"flex items-center gap-1\">\n <DataTablePageButton\n table={table}\n page=\"first\"\n />\n <DataTablePageButton\n table={table}\n page=\"previous\"\n />\n <DataTablePageButton\n table={table}\n page=\"next\"\n />\n <DataTablePageButton\n table={table}\n page=\"last\"\n />\n </div>\n </div>\n </>\n ) : (\n children\n );\n\n const baseProps = {\n 'data-component': 'DataTable.Pagination',\n 'aria-label': 'Paginação',\n className: mergeTwClassNames(\n [\n 'flex',\n 'flex-wrap',\n 'items-center',\n 'justify-between',\n 'gap-x-6',\n 'gap-y-2',\n ],\n className,\n ),\n children: content,\n };\n\n return useRender({\n render,\n defaultTagName: 'nav',\n props: mergeProps(baseProps, rest),\n });\n};\n\nDataTablePagination.displayName = 'DataTable.Pagination';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CA,MAAa,uBAIX,UACG;CACH,MAAM,EAAE,OAAO,QAAQ,WAAW,UAAU,GAAG,SAAS;CAExD,MAAM,UACJ,aAAa,KAAA,IACX,qBAAA,UAAA,EAAA,UAAA,CACG,gBAAgB,OAAO,qBAAqB,KAC3C,oBAAC,wBAAD,EAA+B,MAAQ,CAAA,GAKzC,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA;GACE,oBAAC,yBAAD,EAAgC,MAAQ,CAAA;GACxC,oBAAC,mBAAD,EAA0B,MAAQ,CAAA;GAClC,oBAAC,qBAAD,EAA4B,MAAQ,CAAA;GAEpC,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA;KACE,oBAAC,qBAAD;MACS;MACP,MAAK;KACN,CAAA;KACD,oBAAC,qBAAD;MACS;MACP,MAAK;KACN,CAAA;KACD,oBAAC,qBAAD;MACS;MACP,MAAK;KACN,CAAA;KACD,oBAAC,qBAAD;MACS;MACP,MAAK;KACN,CAAA;IACE;;EACF;CACL,CAAA,CAAA,EAAA,CAAA,IAEF;CAGJ,MAAM,YAAY;EAChB,kBAAkB;EAClB,cAAc;EACd,WAAW,kBACT;GACE;GACA;GACA;GACA;GACA;GACA;EACF,GACA,SACF;EACA,UAAU;CACZ;CAEA,OAAO,UAAU;EACf;EACA,gBAAgB;EAChB,OAAO,WAAW,WAAW,IAAI;CACnC,CAAC;AACH;AAEA,oBAAoB,cAAc"}
|
|
@@ -3,7 +3,7 @@ import "../../../types/index.js";
|
|
|
3
3
|
import { RowData, TableFeatures } from "@tanstack/react-table";
|
|
4
4
|
import { useRender } from "@base-ui/react";
|
|
5
5
|
import React from "react";
|
|
6
|
-
import { MergeOverride } from "@lucasbernardosn/utils";
|
|
6
|
+
import { MergeOverride } from "@lucasbernardosn/ts-utils";
|
|
7
7
|
//#region src/components/data-table/pagination/data-table-row-range.d.ts
|
|
8
8
|
/** As linhas da página atual e o total, para o texto do `DataTable.RowRange`. */
|
|
9
9
|
export type DataTableRowRangeValues = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table-row-range.js","names":[],"sources":["../../../../src/components/data-table/pagination/data-table-row-range.tsx"],"sourcesContent":["import { mergeProps, useRender } from '@base-ui/react';\nimport { mergeTwClassNames } from '@lucasbernardosn/react-ui/utils';\nimport type { MergeOverride } from '@lucasbernardosn/utils';\nimport { shallow, useSelector } from '@tanstack/react-store';\nimport type { RowData, TableFeatures } from '@tanstack/react-table';\nimport type React from 'react';\nimport type { TableWith } from '../../../types';\nimport { getDataTableLoadingWithoutRows } from '../loading/get-data-table-loading-without-rows';\n\n/** As linhas da página atual e o total, para o texto do `DataTable.RowRange`. */\nexport type DataTableRowRangeValues = {\n /** A posição da primeira linha da página, a partir de 1, ou 0 sem linhas. */\n firstRow: number;\n /** A posição da última linha da página, ou 0 sem linhas. */\n lastRow: number;\n /**\n * O total de linhas, ou `-1` sem ele: na paginação pela API, sem o `rowCount` da tabela, e, com\n * `loadingFeature`, na carga sem linhas, antes de o total chegar.\n */\n rowCount: number;\n};\n\nexport type DataTableRowRangeProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n useRender.ComponentProps<'span'>,\n {\n /** A tabela. Exige `rowPaginationFeature`. */\n table: TableWith<TFeatures, TData, 'rowPaginationFeature'>;\n /**\n * Uma função que recebe as posições e o total e devolve o texto.\n * @default ({ firstRow, lastRow, rowCount }) => '11–20 de 243', ou '11–20' sem o total\n */\n children?: (values: DataTableRowRangeValues) => React.ReactNode;\n }\n>;\n\n/**\n * Quais linhas a página mostra, e de quantas: \"11–20 de 243\". Com a paginação pela API, o total\n * vem do `rowCount` da tabela; sem ele, só \"11–20\". Na carga sem linhas, como a primeira, fica\n * vazio: o total ainda não chegou.\n *\n * Marca `role=\"status\"`: quando o intervalo muda, como na troca de página, o leitor de tela\n * anuncia o texto novo sem mover o foco.\n *\n * @example\n * ```tsx\n * <DataTable.RowRange table={table}>\n * {({ rowCount }) => `${rowCount} pessoas`}\n * </DataTable.RowRange>\n * ```\n */\nexport const DataTableRowRange = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableRowRangeProps<TFeatures, TData>,\n) => {\n const { table, render, className, children, ...rest } = props;\n\n /**\n * Re-renderiza quando a página, o tamanho dela ou as linhas mudam. O store, e não só o atom da\n * paginação: as linhas da página e o total mudam com os dados.\n */\n const values = useSelector(\n table.store,\n (): DataTableRowRangeValues => {\n const { pageIndex, pageSize } = table.atoms.pagination.get();\n const pageRowCount = table.getRowModel().rows.length;\n const offset = pageIndex * pageSize;\n\n return {\n firstRow: pageRowCount === 0 ? 0 : offset + 1,\n lastRow: pageRowCount === 0 ? 0 : offset + pageRowCount,\n // Sem o `rowCount`, o `getRowCount()` do TanStack conta as linhas carregadas, que na\n // paginação pela API são só as da página.\n rowCount:\n getDataTableLoadingWithoutRows(table) ||\n (table.options.manualPagination &&\n table.options.rowCount === undefined)\n ? -1\n : table.getRowCount(),\n };\n },\n { compare: shallow },\n );\n\n /** Re-renderiza quando a carga sem linhas começa ou termina. */\n const isLoadingWithoutRows = useSelector(table.store, () =>\n getDataTableLoadingWithoutRows(table),\n );\n\n const range =\n values.lastRow === 0\n ? '0'\n : `${values.firstRow.toLocaleString('pt-BR')}–${values.lastRow.toLocaleString('pt-BR')}`;\n\n /** Na carga sem linhas, \"0\" diria que não há nada, e não que ainda não se sabe. */\n const defaultText = isLoadingWithoutRows\n ? ''\n : values.rowCount === -1\n ? range\n : `${range} de ${values.rowCount.toLocaleString('pt-BR')}`;\n\n const baseProps = {\n 'data-component': 'DataTable.RowRange',\n role: 'status',\n className: mergeTwClassNames(\n ['text-gray-11', 'text-sm', 'tabular-nums', 'whitespace-nowrap'],\n className,\n ),\n children: children === undefined ? defaultText : children(values),\n };\n\n return useRender({\n render,\n defaultTagName: 'span',\n props: mergeProps(baseProps, rest),\n });\n};\n\nDataTableRowRange.displayName = 'DataTable.RowRange';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAqDA,MAAa,qBAIX,UACG;CACH,MAAM,EAAE,OAAO,QAAQ,WAAW,UAAU,GAAG,SAAS;;;;;CAMxD,MAAM,SAAS,YACb,MAAM,aACyB;EAC7B,MAAM,EAAE,WAAW,aAAa,MAAM,MAAM,WAAW,IAAI;EAC3D,MAAM,eAAe,MAAM,YAAY,CAAC,CAAC,KAAK;EAC9C,MAAM,SAAS,YAAY;EAE3B,OAAO;GACL,UAAU,iBAAiB,IAAI,IAAI,SAAS;GAC5C,SAAS,iBAAiB,IAAI,IAAI,SAAS;GAG3C,UACE,+BAA+B,KAAK,KACnC,MAAM,QAAQ,oBACb,MAAM,QAAQ,aAAa,KAAA,IACzB,KACA,MAAM,YAAY;EAC1B;CACF,GACA,EAAE,SAAS,QAAQ,CACrB;;CAGA,MAAM,uBAAuB,YAAY,MAAM,aAC7C,+BAA+B,KAAK,CACtC;CAEA,MAAM,QACJ,OAAO,YAAY,IACf,MACA,GAAG,OAAO,SAAS,eAAe,OAAO,EAAE,GAAG,OAAO,QAAQ,eAAe,OAAO;;CAGzF,MAAM,cAAc,uBAChB,KACA,OAAO,aAAa,KAClB,QACA,GAAG,MAAM,MAAM,OAAO,SAAS,eAAe,OAAO;CAE3D,MAAM,YAAY;EAChB,kBAAkB;EAClB,MAAM;EACN,WAAW,kBACT;GAAC;GAAgB;GAAW;GAAgB;EAAmB,GAC/D,SACF;EACA,UAAU,aAAa,KAAA,IAAY,cAAc,SAAS,MAAM;CAClE;CAEA,OAAO,UAAU;EACf;EACA,gBAAgB;EAChB,OAAO,WAAW,WAAW,IAAI;CACnC,CAAC;AACH;AAEA,kBAAkB,cAAc"}
|
|
1
|
+
{"version":3,"file":"data-table-row-range.js","names":[],"sources":["../../../../src/components/data-table/pagination/data-table-row-range.tsx"],"sourcesContent":["import { mergeProps, useRender } from '@base-ui/react';\nimport { mergeTwClassNames } from '@lucasbernardosn/react-ui/utils';\nimport type { MergeOverride } from '@lucasbernardosn/ts-utils';\nimport { shallow, useSelector } from '@tanstack/react-store';\nimport type { RowData, TableFeatures } from '@tanstack/react-table';\nimport type React from 'react';\nimport type { TableWith } from '../../../types';\nimport { getDataTableLoadingWithoutRows } from '../loading/get-data-table-loading-without-rows';\n\n/** As linhas da página atual e o total, para o texto do `DataTable.RowRange`. */\nexport type DataTableRowRangeValues = {\n /** A posição da primeira linha da página, a partir de 1, ou 0 sem linhas. */\n firstRow: number;\n /** A posição da última linha da página, ou 0 sem linhas. */\n lastRow: number;\n /**\n * O total de linhas, ou `-1` sem ele: na paginação pela API, sem o `rowCount` da tabela, e, com\n * `loadingFeature`, na carga sem linhas, antes de o total chegar.\n */\n rowCount: number;\n};\n\nexport type DataTableRowRangeProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n useRender.ComponentProps<'span'>,\n {\n /** A tabela. Exige `rowPaginationFeature`. */\n table: TableWith<TFeatures, TData, 'rowPaginationFeature'>;\n /**\n * Uma função que recebe as posições e o total e devolve o texto.\n * @default ({ firstRow, lastRow, rowCount }) => '11–20 de 243', ou '11–20' sem o total\n */\n children?: (values: DataTableRowRangeValues) => React.ReactNode;\n }\n>;\n\n/**\n * Quais linhas a página mostra, e de quantas: \"11–20 de 243\". Com a paginação pela API, o total\n * vem do `rowCount` da tabela; sem ele, só \"11–20\". Na carga sem linhas, como a primeira, fica\n * vazio: o total ainda não chegou.\n *\n * Marca `role=\"status\"`: quando o intervalo muda, como na troca de página, o leitor de tela\n * anuncia o texto novo sem mover o foco.\n *\n * @example\n * ```tsx\n * <DataTable.RowRange table={table}>\n * {({ rowCount }) => `${rowCount} pessoas`}\n * </DataTable.RowRange>\n * ```\n */\nexport const DataTableRowRange = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableRowRangeProps<TFeatures, TData>,\n) => {\n const { table, render, className, children, ...rest } = props;\n\n /**\n * Re-renderiza quando a página, o tamanho dela ou as linhas mudam. O store, e não só o atom da\n * paginação: as linhas da página e o total mudam com os dados.\n */\n const values = useSelector(\n table.store,\n (): DataTableRowRangeValues => {\n const { pageIndex, pageSize } = table.atoms.pagination.get();\n const pageRowCount = table.getRowModel().rows.length;\n const offset = pageIndex * pageSize;\n\n return {\n firstRow: pageRowCount === 0 ? 0 : offset + 1,\n lastRow: pageRowCount === 0 ? 0 : offset + pageRowCount,\n // Sem o `rowCount`, o `getRowCount()` do TanStack conta as linhas carregadas, que na\n // paginação pela API são só as da página.\n rowCount:\n getDataTableLoadingWithoutRows(table) ||\n (table.options.manualPagination &&\n table.options.rowCount === undefined)\n ? -1\n : table.getRowCount(),\n };\n },\n { compare: shallow },\n );\n\n /** Re-renderiza quando a carga sem linhas começa ou termina. */\n const isLoadingWithoutRows = useSelector(table.store, () =>\n getDataTableLoadingWithoutRows(table),\n );\n\n const range =\n values.lastRow === 0\n ? '0'\n : `${values.firstRow.toLocaleString('pt-BR')}–${values.lastRow.toLocaleString('pt-BR')}`;\n\n /** Na carga sem linhas, \"0\" diria que não há nada, e não que ainda não se sabe. */\n const defaultText = isLoadingWithoutRows\n ? ''\n : values.rowCount === -1\n ? range\n : `${range} de ${values.rowCount.toLocaleString('pt-BR')}`;\n\n const baseProps = {\n 'data-component': 'DataTable.RowRange',\n role: 'status',\n className: mergeTwClassNames(\n ['text-gray-11', 'text-sm', 'tabular-nums', 'whitespace-nowrap'],\n className,\n ),\n children: children === undefined ? defaultText : children(values),\n };\n\n return useRender({\n render,\n defaultTagName: 'span',\n props: mergeProps(baseProps, rest),\n });\n};\n\nDataTableRowRange.displayName = 'DataTable.RowRange';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAqDA,MAAa,qBAIX,UACG;CACH,MAAM,EAAE,OAAO,QAAQ,WAAW,UAAU,GAAG,SAAS;;;;;CAMxD,MAAM,SAAS,YACb,MAAM,aACyB;EAC7B,MAAM,EAAE,WAAW,aAAa,MAAM,MAAM,WAAW,IAAI;EAC3D,MAAM,eAAe,MAAM,YAAY,CAAC,CAAC,KAAK;EAC9C,MAAM,SAAS,YAAY;EAE3B,OAAO;GACL,UAAU,iBAAiB,IAAI,IAAI,SAAS;GAC5C,SAAS,iBAAiB,IAAI,IAAI,SAAS;GAG3C,UACE,+BAA+B,KAAK,KACnC,MAAM,QAAQ,oBACb,MAAM,QAAQ,aAAa,KAAA,IACzB,KACA,MAAM,YAAY;EAC1B;CACF,GACA,EAAE,SAAS,QAAQ,CACrB;;CAGA,MAAM,uBAAuB,YAAY,MAAM,aAC7C,+BAA+B,KAAK,CACtC;CAEA,MAAM,QACJ,OAAO,YAAY,IACf,MACA,GAAG,OAAO,SAAS,eAAe,OAAO,EAAE,GAAG,OAAO,QAAQ,eAAe,OAAO;;CAGzF,MAAM,cAAc,uBAChB,KACA,OAAO,aAAa,KAClB,QACA,GAAG,MAAM,MAAM,OAAO,SAAS,eAAe,OAAO;CAE3D,MAAM,YAAY;EAChB,kBAAkB;EAClB,MAAM;EACN,WAAW,kBACT;GAAC;GAAgB;GAAW;GAAgB;EAAmB,GAC/D,SACF;EACA,UAAU,aAAa,KAAA,IAAY,cAAc,SAAS,MAAM;CAClE;CAEA,OAAO,UAAU;EACf;EACA,gBAAgB;EAChB,OAAO,WAAW,WAAW,IAAI;CACnC,CAAC;AACH;AAEA,kBAAkB,cAAc"}
|
|
@@ -3,7 +3,7 @@ import "../../../types/index.js";
|
|
|
3
3
|
import { RowData, TableFeatures } from "@tanstack/react-table";
|
|
4
4
|
import { useRender } from "@base-ui/react";
|
|
5
5
|
import React from "react";
|
|
6
|
-
import { MergeOverride } from "@lucasbernardosn/utils";
|
|
6
|
+
import { MergeOverride } from "@lucasbernardosn/ts-utils";
|
|
7
7
|
//#region src/components/data-table/pagination/data-table-selected-count.d.ts
|
|
8
8
|
export type DataTableSelectedCountProps<TFeatures extends TableFeatures, TData extends RowData> = MergeOverride<useRender.ComponentProps<'span'>, {
|
|
9
9
|
/** A tabela. Exige `rowSelectionFeature`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table-selected-count.js","names":[],"sources":["../../../../src/components/data-table/pagination/data-table-selected-count.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 React from 'react';\nimport type { TableWith } from '../../../types';\n\nexport type DataTableSelectedCountProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n useRender.ComponentProps<'span'>,\n {\n /** A tabela. Exige `rowSelectionFeature`. */\n table: TableWith<TFeatures, TData, 'rowSelectionFeature'>;\n /**\n * Uma função que recebe quantas linhas estão marcadas e devolve o texto.\n * @default (count) => '3 selecionadas', '1 selecionada' ou '0 selecionadas'\n */\n children?: (count: number) => React.ReactNode;\n }\n>;\n\n/**\n * Quantas linhas estão marcadas: \"3 selecionadas\". Aparece também sem nenhuma, \"0 selecionadas\":\n * na barra da paginação, o lado esquerdo não some e volta a cada seleção.\n *\n * Conta os ids marcados no estado, e não as linhas carregadas: com a paginação pela API, entram as\n * marcadas em outras páginas. Exige o `getRowId` com o id do registro (ver\n * `DataTable.RowCheckbox`).\n *\n * @example\n * ```tsx\n * <DataTable.SelectedCount table={table}>\n * {(count) => `${count} de ${total}`}\n * </DataTable.SelectedCount>\n * ```\n */\nexport const DataTableSelectedCount = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableSelectedCountProps<TFeatures, TData>,\n) => {\n const { table, render, className, children, ...rest } = props;\n\n /** Re-renderiza quando o número de marcadas muda. */\n const count = useSelector(\n table.atoms.rowSelection,\n (rowSelection) => Object.values(rowSelection).filter(Boolean).length,\n );\n\n const baseProps = {\n 'data-component': 'DataTable.SelectedCount',\n className: mergeTwClassNames(\n [\n 'text-gray-11',\n 'text-sm',\n\n 'tabular-nums',\n 'whitespace-nowrap',\n ],\n className,\n ),\n children:\n children === undefined\n ? `${count.toLocaleString('pt-BR')} ${count === 1 ? 'selecionada' : 'selecionadas'}`\n : children(count),\n };\n\n return useRender({\n render,\n defaultTagName: 'span',\n props: mergeProps(baseProps, rest),\n });\n};\n\nDataTableSelectedCount.displayName = 'DataTable.SelectedCount';\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAuCA,MAAa,0BAIX,UACG;CACH,MAAM,EAAE,OAAO,QAAQ,WAAW,UAAU,GAAG,SAAS;;CAGxD,MAAM,QAAQ,YACZ,MAAM,MAAM,eACX,iBAAiB,OAAO,OAAO,YAAY,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,MAChE;CAEA,MAAM,YAAY;EAChB,kBAAkB;EAClB,WAAW,kBACT;GACE;GACA;GAEA;GACA;EACF,GACA,SACF;EACA,UACE,aAAa,KAAA,IACT,GAAG,MAAM,eAAe,OAAO,EAAE,GAAG,UAAU,IAAI,gBAAgB,mBAClE,SAAS,KAAK;CACtB;CAEA,OAAO,UAAU;EACf;EACA,gBAAgB;EAChB,OAAO,WAAW,WAAW,IAAI;CACnC,CAAC;AACH;AAEA,uBAAuB,cAAc"}
|
|
1
|
+
{"version":3,"file":"data-table-selected-count.js","names":[],"sources":["../../../../src/components/data-table/pagination/data-table-selected-count.tsx"],"sourcesContent":["import { mergeProps, useRender } from '@base-ui/react';\nimport { mergeTwClassNames } from '@lucasbernardosn/react-ui/utils';\nimport type { MergeOverride } from '@lucasbernardosn/ts-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';\n\nexport type DataTableSelectedCountProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n useRender.ComponentProps<'span'>,\n {\n /** A tabela. Exige `rowSelectionFeature`. */\n table: TableWith<TFeatures, TData, 'rowSelectionFeature'>;\n /**\n * Uma função que recebe quantas linhas estão marcadas e devolve o texto.\n * @default (count) => '3 selecionadas', '1 selecionada' ou '0 selecionadas'\n */\n children?: (count: number) => React.ReactNode;\n }\n>;\n\n/**\n * Quantas linhas estão marcadas: \"3 selecionadas\". Aparece também sem nenhuma, \"0 selecionadas\":\n * na barra da paginação, o lado esquerdo não some e volta a cada seleção.\n *\n * Conta os ids marcados no estado, e não as linhas carregadas: com a paginação pela API, entram as\n * marcadas em outras páginas. Exige o `getRowId` com o id do registro (ver\n * `DataTable.RowCheckbox`).\n *\n * @example\n * ```tsx\n * <DataTable.SelectedCount table={table}>\n * {(count) => `${count} de ${total}`}\n * </DataTable.SelectedCount>\n * ```\n */\nexport const DataTableSelectedCount = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableSelectedCountProps<TFeatures, TData>,\n) => {\n const { table, render, className, children, ...rest } = props;\n\n /** Re-renderiza quando o número de marcadas muda. */\n const count = useSelector(\n table.atoms.rowSelection,\n (rowSelection) => Object.values(rowSelection).filter(Boolean).length,\n );\n\n const baseProps = {\n 'data-component': 'DataTable.SelectedCount',\n className: mergeTwClassNames(\n [\n 'text-gray-11',\n 'text-sm',\n\n 'tabular-nums',\n 'whitespace-nowrap',\n ],\n className,\n ),\n children:\n children === undefined\n ? `${count.toLocaleString('pt-BR')} ${count === 1 ? 'selecionada' : 'selecionadas'}`\n : children(count),\n };\n\n return useRender({\n render,\n defaultTagName: 'span',\n props: mergeProps(baseProps, rest),\n });\n};\n\nDataTableSelectedCount.displayName = 'DataTable.SelectedCount';\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAuCA,MAAa,0BAIX,UACG;CACH,MAAM,EAAE,OAAO,QAAQ,WAAW,UAAU,GAAG,SAAS;;CAGxD,MAAM,QAAQ,YACZ,MAAM,MAAM,eACX,iBAAiB,OAAO,OAAO,YAAY,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,MAChE;CAEA,MAAM,YAAY;EAChB,kBAAkB;EAClB,WAAW,kBACT;GACE;GACA;GAEA;GACA;EACF,GACA,SACF;EACA,UACE,aAAa,KAAA,IACT,GAAG,MAAM,eAAe,OAAO,EAAE,GAAG,UAAU,IAAI,gBAAgB,mBAClE,SAAS,KAAK;CACtB;CAEA,OAAO,UAAU;EACf;EACA,gBAAgB;EAChB,OAAO,WAAW,WAAW,IAAI;CACnC,CAAC;AACH;AAEA,uBAAuB,cAAc"}
|
|
@@ -3,7 +3,7 @@ import "../../../types/index.js";
|
|
|
3
3
|
import { RowData, TableFeatures } from "@tanstack/react-table";
|
|
4
4
|
import { useRender } from "@base-ui/react";
|
|
5
5
|
import React from "react";
|
|
6
|
-
import { MergeOverride } from "@lucasbernardosn/utils";
|
|
6
|
+
import { MergeOverride } from "@lucasbernardosn/ts-utils";
|
|
7
7
|
//#region src/components/data-table/resize/data-table-resize-handle.d.ts
|
|
8
8
|
export type DataTableResizeHandleProps<TFeatures extends TableFeatures, TData extends RowData> = MergeOverride<useRender.ComponentProps<'div'>, {
|
|
9
9
|
/** O header da coluna. Exige `columnSizingFeature` e `columnResizingFeature`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table-resize-handle.js","names":[],"sources":["../../../../src/components/data-table/resize/data-table-resize-handle.tsx"],"sourcesContent":["import { mergeProps, useRender } from '@base-ui/react';\nimport { InteractionShield } from '@lucasbernardosn/react-ui/utilities/interaction-shield';\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 React from 'react';\nimport { useRef } from 'react';\nimport type { HeaderWith } from '../../../types';\nimport { useDataTableResizeScroll } from './use-data-table-resize-scroll';\n\nexport type DataTableResizeHandleProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n useRender.ComponentProps<'div'>,\n {\n /** O header da coluna. Exige `columnSizingFeature` e `columnResizingFeature`. */\n header: HeaderWith<\n TFeatures,\n TData,\n 'columnResizingFeature' | 'columnSizingFeature'\n >;\n }\n>;\n\n/**\n * Área de agarre para redimensionar uma coluna, sobre a linha vertical do fim do header (que\n * precisa ser `relative`). Arrastar redimensiona; duplo clique devolve a coluna ao tamanho\n * definido.\n *\n * A caixa tem largura zero, e a área de agarre é um `::before` transparente de 12px centrado na\n * linha, metade sobre a coluna vizinha; na última coluna e antes de uma fixada do fim, toda do\n * lado de dentro. No repouso não aparece; no hover e no arrasto, o handle vira a âncora da\n * linha-guia, que a `DataTable.ScrollArea` desenha na altura toda da tabela.\n * Quando a borda chega à beira de uma fixada do fim ou ao fim da área visível, a rolagem\n * acompanha o arrasto. Numa coluna que não redimensiona (`enableResizing: false`), não\n * renderiza.\n *\n * Durante o arrasto, o `InteractionShield` do `ui` cobre a página: nada, dentro ou fora da\n * tabela, reage ao ponteiro, o cursor de resize vale em toda parte, e o texto não é selecionado.\n * A roda do mouse, por cima dele, não rola a tabela.\n *\n * Exige `columnResizeMode: 'onChange'` na tabela. Com o padrão do TanStack, `'onEnd'`, o tamanho\n * só muda ao soltar: no arrasto nada anda na tela (nem a coluna, nem o handle, nem a guia), e a\n * coluna pula no fim.\n *\n * @example\n * ```tsx\n * const table = useTable({ features, columns, data, columnResizeMode: 'onChange' });\n *\n * <DataTable.HeaderCell header={header}>\n * <DataTable.HeaderContent header={header} />\n * <DataTable.ResizeHandle header={header} />\n * </DataTable.HeaderCell>\n * ```\n */\nexport const DataTableResizeHandle = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableResizeHandleProps<TFeatures, TData>,\n) => {\n const { header, render, className, ref, ...rest } = props;\n\n const handleRef = useRef<HTMLDivElement>(null);\n\n /**\n * O atom do resize muda a cada tick do arrasto, mas o booleano só no começo e no fim: o handle\n * re-renderiza duas vezes por arrasto, e só o da coluna arrastada.\n */\n const isResizing = useSelector(header.column.table.atoms.columnResizing, () =>\n header.column.getIsResizing(),\n );\n\n useDataTableResizeScroll(header.column.table, isResizing, handleRef);\n\n const onResizeStart = header.getResizeHandler();\n\n /**\n * O duplo clique pelo `detail` do `mousedown`, que conta os cliques, e não pelo `dblclick`: o\n * arrasto começa no primeiro `mousedown`, o shield cobre o handle, e o `mouseup` cai nele. O\n * navegador então não manda o `click` nem o `dblclick` ao handle.\n */\n const handleMouseDown = (event: React.MouseEvent<HTMLDivElement>) => {\n if (event.detail === 2) {\n header.column.resetSize();\n\n return;\n }\n\n onResizeStart(event);\n };\n\n const baseProps = {\n 'data-component': 'DataTable.ResizeHandle',\n 'data-resizing': isResizing ? '' : undefined,\n // Só ponteiro: sem resize por teclado, um `separator` prometeria teclas que não existem.\n 'aria-hidden': true,\n onMouseDown: handleMouseDown,\n onTouchStart: onResizeStart,\n className: mergeTwClassNames(\n [\n // Sobre a linha vertical: o `right-0` é o fim do padding, e a borda de 1px que o\n // `divide-x` põe na célula vem logo depois. A última da linha não tem borda, e o\n // `right-px` põe o handle no mesmo ponto em relação ao fim dela. Antes de uma fixada do\n // fim, a célula também perde a borda, mas a linha passa a ser a da fixada, logo depois:\n // o `right-0` continua certo. Pela posição no DOM, com os seletores das bordas da\n // `DataTable.HeaderRow`, o handle e a borda não têm como discordar.\n 'absolute',\n 'top-0',\n 'right-0',\n 'in-[[role=columnheader]:last-child]:right-px',\n 'z-10',\n\n 'h-full',\n\n 'cursor-col-resize',\n // Com um menu aberto no gatilho da célula, o backdrop do Base UI deixa um recorte do\n // tamanho do gatilho, e a metade de dentro da área de agarre cairia nele: o hover acenderia\n // a linha-guia com o menu aberto.\n 'in-[[role=columnheader]:has([data-popup-open])]:pointer-events-none',\n // Sem isto, o arrasto no toque rola a página em vez de redimensionar.\n 'touch-none',\n 'select-none',\n\n // Área de agarre centrada na linha. Conteúdo recortado não recebe clique, então nada\n // entre o handle e o header pode ter `overflow: hidden`.\n 'before:absolute',\n 'before:top-0',\n 'before:right-0',\n 'before:h-full',\n 'before:w-3',\n 'before:translate-x-1.5',\n 'before:content-[\"\"]',\n\n // Onde a metade de fora não serve, os 12px ficam todos do lado de dentro. Na última da\n // linha, ela passaria do fim da tabela e acenderia a barra de rolagem horizontal sem\n // haver o que rolar; antes de uma fixada do fim, ficaria por baixo dela, sem pegar o\n // clique.\n 'in-[[role=columnheader]:last-child]:before:translate-x-0',\n 'in-[[role=columnheader]:has(+[data-pinned=end])]:before:translate-x-0',\n\n // A linha de 2px no cabeçalho, sobre a borda e 1px antes dela, no hover e no arrasto. Onde\n // há anchor positioning, a linha-guia cobre esta no mesmo lugar e segue pelo corpo; sem\n // ele, fica só esta.\n 'after:absolute',\n 'after:inset-y-0',\n 'after:left-0',\n 'after:w-0.5',\n 'after:-translate-x-1/2',\n 'after:content-[\"\"]',\n 'hover:after:bg-gray-9',\n 'data-resizing:after:bg-black',\n 'dark:data-resizing:after:bg-white',\n\n // A âncora da linha-guia (ver `DataTable.ScrollArea`), no hover e no arrasto. Um nome só\n // basta: no arrasto, o shield cobre os outros handles, e nenhum fica em hover junto com\n // o arrastado. Com o nome repetido, a guia iria para o último.\n 'hover:[anchor-name:--data-table-resize-handle]',\n 'data-resizing:[anchor-name:--data-table-resize-handle]',\n ],\n className,\n ),\n };\n\n const element = useRender({\n render,\n defaultTagName: 'div',\n ref: [handleRef, ref ?? null],\n props: mergeProps(baseProps, rest),\n });\n\n return header.column.getCanResize() ? (\n <>\n {element}\n <InteractionShield\n active={isResizing}\n cursor=\"col-resize\"\n />\n </>\n ) : null;\n};\n\nDataTableResizeHandle.displayName = 'DataTable.ResizeHandle';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyDA,MAAa,yBAIX,UACG;CACH,MAAM,EAAE,QAAQ,QAAQ,WAAW,KAAK,GAAG,SAAS;CAEpD,MAAM,YAAY,OAAuB,IAAI;;;;;CAM7C,MAAM,aAAa,YAAY,OAAO,OAAO,MAAM,MAAM,sBACvD,OAAO,OAAO,cAAc,CAC9B;CAEA,yBAAyB,OAAO,OAAO,OAAO,YAAY,SAAS;CAEnE,MAAM,gBAAgB,OAAO,iBAAiB;;;;;;CAO9C,MAAM,mBAAmB,UAA4C;EACnE,IAAI,MAAM,WAAW,GAAG;GACtB,OAAO,OAAO,UAAU;GAExB;EACF;EAEA,cAAc,KAAK;CACrB;CAEA,MAAM,YAAY;EAChB,kBAAkB;EAClB,iBAAiB,aAAa,KAAK,KAAA;EAEnC,eAAe;EACf,aAAa;EACb,cAAc;EACd,WAAW,kBACT;GAOE;GACA;GACA;GACA;GACA;GAEA;GAEA;GAIA;GAEA;GACA;GAIA;GACA;GACA;GACA;GACA;GACA;GACA;GAMA;GACA;GAKA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAKA;GACA;EACF,GACA,SACF;CACF;CAEA,MAAM,UAAU,UAAU;EACxB;EACA,gBAAgB;EAChB,KAAK,CAAC,WAAW,OAAO,IAAI;EAC5B,OAAO,WAAW,WAAW,IAAI;CACnC,CAAC;CAED,OAAO,OAAO,OAAO,aAAa,IAChC,qBAAA,UAAA,EAAA,UAAA,CACG,SACD,oBAAC,mBAAD;EACE,QAAQ;EACR,QAAO;CACR,CAAA,CACD,EAAA,CAAA,IACA;AACN;AAEA,sBAAsB,cAAc"}
|
|
1
|
+
{"version":3,"file":"data-table-resize-handle.js","names":[],"sources":["../../../../src/components/data-table/resize/data-table-resize-handle.tsx"],"sourcesContent":["import { mergeProps, useRender } from '@base-ui/react';\nimport { InteractionShield } from '@lucasbernardosn/react-ui/utilities/interaction-shield';\nimport { mergeTwClassNames } from '@lucasbernardosn/react-ui/utils';\nimport type { MergeOverride } from '@lucasbernardosn/ts-utils';\nimport { useSelector } from '@tanstack/react-store';\nimport type { RowData, TableFeatures } from '@tanstack/react-table';\nimport type React from 'react';\nimport { useRef } from 'react';\nimport type { HeaderWith } from '../../../types';\nimport { useDataTableResizeScroll } from './use-data-table-resize-scroll';\n\nexport type DataTableResizeHandleProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n useRender.ComponentProps<'div'>,\n {\n /** O header da coluna. Exige `columnSizingFeature` e `columnResizingFeature`. */\n header: HeaderWith<\n TFeatures,\n TData,\n 'columnResizingFeature' | 'columnSizingFeature'\n >;\n }\n>;\n\n/**\n * Área de agarre para redimensionar uma coluna, sobre a linha vertical do fim do header (que\n * precisa ser `relative`). Arrastar redimensiona; duplo clique devolve a coluna ao tamanho\n * definido.\n *\n * A caixa tem largura zero, e a área de agarre é um `::before` transparente de 12px centrado na\n * linha, metade sobre a coluna vizinha; na última coluna e antes de uma fixada do fim, toda do\n * lado de dentro. No repouso não aparece; no hover e no arrasto, o handle vira a âncora da\n * linha-guia, que a `DataTable.ScrollArea` desenha na altura toda da tabela.\n * Quando a borda chega à beira de uma fixada do fim ou ao fim da área visível, a rolagem\n * acompanha o arrasto. Numa coluna que não redimensiona (`enableResizing: false`), não\n * renderiza.\n *\n * Durante o arrasto, o `InteractionShield` do `ui` cobre a página: nada, dentro ou fora da\n * tabela, reage ao ponteiro, o cursor de resize vale em toda parte, e o texto não é selecionado.\n * A roda do mouse, por cima dele, não rola a tabela.\n *\n * Exige `columnResizeMode: 'onChange'` na tabela. Com o padrão do TanStack, `'onEnd'`, o tamanho\n * só muda ao soltar: no arrasto nada anda na tela (nem a coluna, nem o handle, nem a guia), e a\n * coluna pula no fim.\n *\n * @example\n * ```tsx\n * const table = useTable({ features, columns, data, columnResizeMode: 'onChange' });\n *\n * <DataTable.HeaderCell header={header}>\n * <DataTable.HeaderContent header={header} />\n * <DataTable.ResizeHandle header={header} />\n * </DataTable.HeaderCell>\n * ```\n */\nexport const DataTableResizeHandle = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableResizeHandleProps<TFeatures, TData>,\n) => {\n const { header, render, className, ref, ...rest } = props;\n\n const handleRef = useRef<HTMLDivElement>(null);\n\n /**\n * O atom do resize muda a cada tick do arrasto, mas o booleano só no começo e no fim: o handle\n * re-renderiza duas vezes por arrasto, e só o da coluna arrastada.\n */\n const isResizing = useSelector(header.column.table.atoms.columnResizing, () =>\n header.column.getIsResizing(),\n );\n\n useDataTableResizeScroll(header.column.table, isResizing, handleRef);\n\n const onResizeStart = header.getResizeHandler();\n\n /**\n * O duplo clique pelo `detail` do `mousedown`, que conta os cliques, e não pelo `dblclick`: o\n * arrasto começa no primeiro `mousedown`, o shield cobre o handle, e o `mouseup` cai nele. O\n * navegador então não manda o `click` nem o `dblclick` ao handle.\n */\n const handleMouseDown = (event: React.MouseEvent<HTMLDivElement>) => {\n if (event.detail === 2) {\n header.column.resetSize();\n\n return;\n }\n\n onResizeStart(event);\n };\n\n const baseProps = {\n 'data-component': 'DataTable.ResizeHandle',\n 'data-resizing': isResizing ? '' : undefined,\n // Só ponteiro: sem resize por teclado, um `separator` prometeria teclas que não existem.\n 'aria-hidden': true,\n onMouseDown: handleMouseDown,\n onTouchStart: onResizeStart,\n className: mergeTwClassNames(\n [\n // Sobre a linha vertical: o `right-0` é o fim do padding, e a borda de 1px que o\n // `divide-x` põe na célula vem logo depois. A última da linha não tem borda, e o\n // `right-px` põe o handle no mesmo ponto em relação ao fim dela. Antes de uma fixada do\n // fim, a célula também perde a borda, mas a linha passa a ser a da fixada, logo depois:\n // o `right-0` continua certo. Pela posição no DOM, com os seletores das bordas da\n // `DataTable.HeaderRow`, o handle e a borda não têm como discordar.\n 'absolute',\n 'top-0',\n 'right-0',\n 'in-[[role=columnheader]:last-child]:right-px',\n 'z-10',\n\n 'h-full',\n\n 'cursor-col-resize',\n // Com um menu aberto no gatilho da célula, o backdrop do Base UI deixa um recorte do\n // tamanho do gatilho, e a metade de dentro da área de agarre cairia nele: o hover acenderia\n // a linha-guia com o menu aberto.\n 'in-[[role=columnheader]:has([data-popup-open])]:pointer-events-none',\n // Sem isto, o arrasto no toque rola a página em vez de redimensionar.\n 'touch-none',\n 'select-none',\n\n // Área de agarre centrada na linha. Conteúdo recortado não recebe clique, então nada\n // entre o handle e o header pode ter `overflow: hidden`.\n 'before:absolute',\n 'before:top-0',\n 'before:right-0',\n 'before:h-full',\n 'before:w-3',\n 'before:translate-x-1.5',\n 'before:content-[\"\"]',\n\n // Onde a metade de fora não serve, os 12px ficam todos do lado de dentro. Na última da\n // linha, ela passaria do fim da tabela e acenderia a barra de rolagem horizontal sem\n // haver o que rolar; antes de uma fixada do fim, ficaria por baixo dela, sem pegar o\n // clique.\n 'in-[[role=columnheader]:last-child]:before:translate-x-0',\n 'in-[[role=columnheader]:has(+[data-pinned=end])]:before:translate-x-0',\n\n // A linha de 2px no cabeçalho, sobre a borda e 1px antes dela, no hover e no arrasto. Onde\n // há anchor positioning, a linha-guia cobre esta no mesmo lugar e segue pelo corpo; sem\n // ele, fica só esta.\n 'after:absolute',\n 'after:inset-y-0',\n 'after:left-0',\n 'after:w-0.5',\n 'after:-translate-x-1/2',\n 'after:content-[\"\"]',\n 'hover:after:bg-gray-9',\n 'data-resizing:after:bg-black',\n 'dark:data-resizing:after:bg-white',\n\n // A âncora da linha-guia (ver `DataTable.ScrollArea`), no hover e no arrasto. Um nome só\n // basta: no arrasto, o shield cobre os outros handles, e nenhum fica em hover junto com\n // o arrastado. Com o nome repetido, a guia iria para o último.\n 'hover:[anchor-name:--data-table-resize-handle]',\n 'data-resizing:[anchor-name:--data-table-resize-handle]',\n ],\n className,\n ),\n };\n\n const element = useRender({\n render,\n defaultTagName: 'div',\n ref: [handleRef, ref ?? null],\n props: mergeProps(baseProps, rest),\n });\n\n return header.column.getCanResize() ? (\n <>\n {element}\n <InteractionShield\n active={isResizing}\n cursor=\"col-resize\"\n />\n </>\n ) : null;\n};\n\nDataTableResizeHandle.displayName = 'DataTable.ResizeHandle';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyDA,MAAa,yBAIX,UACG;CACH,MAAM,EAAE,QAAQ,QAAQ,WAAW,KAAK,GAAG,SAAS;CAEpD,MAAM,YAAY,OAAuB,IAAI;;;;;CAM7C,MAAM,aAAa,YAAY,OAAO,OAAO,MAAM,MAAM,sBACvD,OAAO,OAAO,cAAc,CAC9B;CAEA,yBAAyB,OAAO,OAAO,OAAO,YAAY,SAAS;CAEnE,MAAM,gBAAgB,OAAO,iBAAiB;;;;;;CAO9C,MAAM,mBAAmB,UAA4C;EACnE,IAAI,MAAM,WAAW,GAAG;GACtB,OAAO,OAAO,UAAU;GAExB;EACF;EAEA,cAAc,KAAK;CACrB;CAEA,MAAM,YAAY;EAChB,kBAAkB;EAClB,iBAAiB,aAAa,KAAK,KAAA;EAEnC,eAAe;EACf,aAAa;EACb,cAAc;EACd,WAAW,kBACT;GAOE;GACA;GACA;GACA;GACA;GAEA;GAEA;GAIA;GAEA;GACA;GAIA;GACA;GACA;GACA;GACA;GACA;GACA;GAMA;GACA;GAKA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAKA;GACA;EACF,GACA,SACF;CACF;CAEA,MAAM,UAAU,UAAU;EACxB;EACA,gBAAgB;EAChB,KAAK,CAAC,WAAW,OAAO,IAAI;EAC5B,OAAO,WAAW,WAAW,IAAI;CACnC,CAAC;CAED,OAAO,OAAO,OAAO,aAAa,IAChC,qBAAA,UAAA,EAAA,UAAA,CACG,SACD,oBAAC,mBAAD;EACE,QAAQ;EACR,QAAO;CACR,CAAA,CACD,EAAA,CAAA,IACA;AACN;AAEA,sBAAsB,cAAc"}
|
|
@@ -2,7 +2,7 @@ import { TableWith } from "../../../types/table-with.js";
|
|
|
2
2
|
import "../../../types/index.js";
|
|
3
3
|
import { RowData, TableFeatures } from "@tanstack/react-table";
|
|
4
4
|
import { useRender } from "@base-ui/react";
|
|
5
|
-
import { MergeOverride } from "@lucasbernardosn/utils";
|
|
5
|
+
import { MergeOverride } from "@lucasbernardosn/ts-utils";
|
|
6
6
|
//#region src/components/data-table/root/data-table-root.d.ts
|
|
7
7
|
export type DataTableRootProps<TFeatures extends TableFeatures, TData extends RowData> = MergeOverride<useRender.ComponentProps<'div'>, {
|
|
8
8
|
/** A tabela do `useTable`. Exige `columnSizingFeature`. */
|
|
@@ -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)]',\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"}
|
|
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/ts-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"}
|
|
@@ -2,7 +2,7 @@ import { RowWith } from "../../../types/table-with.js";
|
|
|
2
2
|
import "../../../types/index.js";
|
|
3
3
|
import { RowData, TableFeatures } from "@tanstack/react-table";
|
|
4
4
|
import { Checkbox } from "@lucasbernardosn/react-ui/fields/checkbox";
|
|
5
|
-
import { MergeOverride } from "@lucasbernardosn/utils";
|
|
5
|
+
import { MergeOverride } from "@lucasbernardosn/ts-utils";
|
|
6
6
|
//#region src/components/data-table/selection/data-table-row-checkbox.d.ts
|
|
7
7
|
export type DataTableRowCheckboxProps<TFeatures extends TableFeatures, TData extends RowData> = MergeOverride<Omit<Checkbox.RootProps, 'checked' | 'defaultChecked' | 'indeterminate' | 'onCheckedChange'>, {
|
|
8
8
|
/** A linha. Exige `rowSelectionFeature`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table-row-checkbox.js","names":[],"sources":["../../../../src/components/data-table/selection/data-table-row-checkbox.tsx"],"sourcesContent":["import { Checkbox } from '@lucasbernardosn/react-ui/fields/checkbox';\nimport type { MergeOverride } from '@lucasbernardosn/utils';\nimport { useSelector } from '@tanstack/react-store';\nimport type { RowData, TableFeatures } from '@tanstack/react-table';\nimport type { RowWith } from '../../../types';\nimport { hasRowFeature } from '../../../utils';\n\nexport type DataTableRowCheckboxProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n Omit<\n Checkbox.RootProps,\n 'checked' | 'defaultChecked' | 'indeterminate' | 'onCheckedChange'\n >,\n {\n /** A linha. Exige `rowSelectionFeature`. */\n row: RowWith<TFeatures, TData, 'rowSelectionFeature'>;\n }\n>;\n\n/**\n * O checkbox de seleção de uma linha, para a célula de uma coluna de seleção. Shift+clique\n * seleciona o intervalo desde a última linha marcada (`enableRowRangeSelection: false` desliga).\n * Numa linha que não seleciona (`enableRowSelection`), fica desabilitado; com sub-linhas em parte\n * selecionadas, mostra o estado misto.\n *\n * A seleção guarda só os ids das linhas (`{ [rowId]: true }`) e sobrevive à troca de página: com\n * a paginação pela API, os ids de outras páginas ficam no estado, e a linha volta marcada quando\n * a página volta. Para isso, a tabela precisa do `getRowId` com o id do registro: sem ele, o id é\n * a posição na página, que se repete em todas, e marcar a primeira linha de uma marcaria a\n * primeira de todas. Os dados das linhas de outras páginas não estão na tabela\n * (`getSelectedRowModel()` só traz as carregadas): para agir sobre a seleção, mande os ids à API\n * e limpe com `table.resetRowSelection()` depois.\n *\n * Assina só a seleção. As props do `Checkbox.Root` passam adiante, como `colorScheme` e\n * `aria-label`.\n */\nexport const DataTableRowCheckbox = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableRowCheckboxProps<TFeatures, TData>,\n) => {\n const { row, children, ...rest } = props;\n\n /**\n * O estado do checkbox num valor só, para uma assinatura por linha. Re-renderiza quando muda a\n * seleção desta linha ou das sub-linhas; as sub-linhas mudam com os dados, que já trazem uma\n * linha nova por prop.\n */\n const checkedState = useSelector(row.table.atoms.rowSelection, () =>\n row.getIsSelected()\n ? 'checked'\n : row.getIsSomeSelected()\n ? 'indeterminate'\n : 'unchecked',\n );\n\n return (\n <Checkbox.Root\n data-component=\"DataTable.RowCheckbox\"\n aria-label=\"Selecionar linha\"\n checked={checkedState === 'checked'}\n indeterminate={checkedState === 'indeterminate'}\n disabled={!row.getCanSelect()}\n // Com a navegação, a tabela tem um ponto de Tab só, a linha ativa, e o Espaço nela alterna\n // a seleção. O clique continua.\n tabIndex={hasRowFeature(row, 'activeRowFeature') ? -1 : undefined}\n // O handler lê `target.checked` e o Shift do evento; o Base UI entrega os dois separados.\n onCheckedChange={(checked, eventDetails) =>\n row.getToggleSelectedHandler()({\n target: { checked },\n nativeEvent: eventDetails.event,\n })\n }\n {...rest}\n >\n {children === undefined ? <Checkbox.Indicator /> : children}\n </Checkbox.Root>\n );\n};\n\nDataTableRowCheckbox.displayName = 'DataTable.RowCheckbox';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAsCA,MAAa,wBAIX,UACG;CACH,MAAM,EAAE,KAAK,UAAU,GAAG,SAAS;;;;;;CAOnC,MAAM,eAAe,YAAY,IAAI,MAAM,MAAM,oBAC/C,IAAI,cAAc,IACd,YACA,IAAI,kBAAkB,IACpB,kBACA,WACR;CAEA,OACE,oBAAC,SAAS,MAAV;EACE,kBAAe;EACf,cAAW;EACX,SAAS,iBAAiB;EAC1B,eAAe,iBAAiB;EAChC,UAAU,CAAC,IAAI,aAAa;EAG5B,UAAU,cAAc,KAAK,kBAAkB,IAAI,KAAK,KAAA;EAExD,kBAAkB,SAAS,iBACzB,IAAI,yBAAyB,CAAC,CAAC;GAC7B,QAAQ,EAAE,QAAQ;GAClB,aAAa,aAAa;EAC5B,CAAC;EAEH,GAAI;EAEH,UAAA,aAAa,KAAA,IAAY,oBAAC,SAAS,WAAV,CAAqB,CAAA,IAAI;CACtC,CAAA;AAEnB;AAEA,qBAAqB,cAAc"}
|
|
1
|
+
{"version":3,"file":"data-table-row-checkbox.js","names":[],"sources":["../../../../src/components/data-table/selection/data-table-row-checkbox.tsx"],"sourcesContent":["import { Checkbox } from '@lucasbernardosn/react-ui/fields/checkbox';\nimport type { MergeOverride } from '@lucasbernardosn/ts-utils';\nimport { useSelector } from '@tanstack/react-store';\nimport type { RowData, TableFeatures } from '@tanstack/react-table';\nimport type { RowWith } from '../../../types';\nimport { hasRowFeature } from '../../../utils';\n\nexport type DataTableRowCheckboxProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n Omit<\n Checkbox.RootProps,\n 'checked' | 'defaultChecked' | 'indeterminate' | 'onCheckedChange'\n >,\n {\n /** A linha. Exige `rowSelectionFeature`. */\n row: RowWith<TFeatures, TData, 'rowSelectionFeature'>;\n }\n>;\n\n/**\n * O checkbox de seleção de uma linha, para a célula de uma coluna de seleção. Shift+clique\n * seleciona o intervalo desde a última linha marcada (`enableRowRangeSelection: false` desliga).\n * Numa linha que não seleciona (`enableRowSelection`), fica desabilitado; com sub-linhas em parte\n * selecionadas, mostra o estado misto.\n *\n * A seleção guarda só os ids das linhas (`{ [rowId]: true }`) e sobrevive à troca de página: com\n * a paginação pela API, os ids de outras páginas ficam no estado, e a linha volta marcada quando\n * a página volta. Para isso, a tabela precisa do `getRowId` com o id do registro: sem ele, o id é\n * a posição na página, que se repete em todas, e marcar a primeira linha de uma marcaria a\n * primeira de todas. Os dados das linhas de outras páginas não estão na tabela\n * (`getSelectedRowModel()` só traz as carregadas): para agir sobre a seleção, mande os ids à API\n * e limpe com `table.resetRowSelection()` depois.\n *\n * Assina só a seleção. As props do `Checkbox.Root` passam adiante, como `colorScheme` e\n * `aria-label`.\n */\nexport const DataTableRowCheckbox = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableRowCheckboxProps<TFeatures, TData>,\n) => {\n const { row, children, ...rest } = props;\n\n /**\n * O estado do checkbox num valor só, para uma assinatura por linha. Re-renderiza quando muda a\n * seleção desta linha ou das sub-linhas; as sub-linhas mudam com os dados, que já trazem uma\n * linha nova por prop.\n */\n const checkedState = useSelector(row.table.atoms.rowSelection, () =>\n row.getIsSelected()\n ? 'checked'\n : row.getIsSomeSelected()\n ? 'indeterminate'\n : 'unchecked',\n );\n\n return (\n <Checkbox.Root\n data-component=\"DataTable.RowCheckbox\"\n aria-label=\"Selecionar linha\"\n checked={checkedState === 'checked'}\n indeterminate={checkedState === 'indeterminate'}\n disabled={!row.getCanSelect()}\n // Com a navegação, a tabela tem um ponto de Tab só, a linha ativa, e o Espaço nela alterna\n // a seleção. O clique continua.\n tabIndex={hasRowFeature(row, 'activeRowFeature') ? -1 : undefined}\n // O handler lê `target.checked` e o Shift do evento; o Base UI entrega os dois separados.\n onCheckedChange={(checked, eventDetails) =>\n row.getToggleSelectedHandler()({\n target: { checked },\n nativeEvent: eventDetails.event,\n })\n }\n {...rest}\n >\n {children === undefined ? <Checkbox.Indicator /> : children}\n </Checkbox.Root>\n );\n};\n\nDataTableRowCheckbox.displayName = 'DataTable.RowCheckbox';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAsCA,MAAa,wBAIX,UACG;CACH,MAAM,EAAE,KAAK,UAAU,GAAG,SAAS;;;;;;CAOnC,MAAM,eAAe,YAAY,IAAI,MAAM,MAAM,oBAC/C,IAAI,cAAc,IACd,YACA,IAAI,kBAAkB,IACpB,kBACA,WACR;CAEA,OACE,oBAAC,SAAS,MAAV;EACE,kBAAe;EACf,cAAW;EACX,SAAS,iBAAiB;EAC1B,eAAe,iBAAiB;EAChC,UAAU,CAAC,IAAI,aAAa;EAG5B,UAAU,cAAc,KAAK,kBAAkB,IAAI,KAAK,KAAA;EAExD,kBAAkB,SAAS,iBACzB,IAAI,yBAAyB,CAAC,CAAC;GAC7B,QAAQ,EAAE,QAAQ;GAClB,aAAa,aAAa;EAC5B,CAAC;EAEH,GAAI;EAEH,UAAA,aAAa,KAAA,IAAY,oBAAC,SAAS,WAAV,CAAqB,CAAA,IAAI;CACtC,CAAA;AAEnB;AAEA,qBAAqB,cAAc"}
|
|
@@ -2,7 +2,7 @@ import { TableWith } from "../../../types/table-with.js";
|
|
|
2
2
|
import "../../../types/index.js";
|
|
3
3
|
import { RowData, TableFeatures } from "@tanstack/react-table";
|
|
4
4
|
import { Checkbox } from "@lucasbernardosn/react-ui/fields/checkbox";
|
|
5
|
-
import { MergeOverride } from "@lucasbernardosn/utils";
|
|
5
|
+
import { MergeOverride } from "@lucasbernardosn/ts-utils";
|
|
6
6
|
//#region src/components/data-table/selection/data-table-select-all-checkbox.d.ts
|
|
7
7
|
export type DataTableSelectAllCheckboxProps<TFeatures extends TableFeatures, TData extends RowData> = MergeOverride<Omit<Checkbox.RootProps, 'checked' | 'defaultChecked' | 'indeterminate' | 'onCheckedChange'>, {
|
|
8
8
|
/** A tabela. Exige `rowSelectionFeature`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table-select-all-checkbox.js","names":[],"sources":["../../../../src/components/data-table/selection/data-table-select-all-checkbox.tsx"],"sourcesContent":["import { Checkbox } from '@lucasbernardosn/react-ui/fields/checkbox';\nimport type { MergeOverride } from '@lucasbernardosn/utils';\nimport { useSelector } from '@tanstack/react-store';\nimport type { RowData, TableFeatures } from '@tanstack/react-table';\nimport type { TableWith } from '../../../types';\nimport { hasTableFeature } from '../../../utils';\n\nexport type DataTableSelectAllCheckboxProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n Omit<\n Checkbox.RootProps,\n 'checked' | 'defaultChecked' | 'indeterminate' | 'onCheckedChange'\n >,\n {\n /** A tabela. Exige `rowSelectionFeature`. */\n table: TableWith<TFeatures, TData, 'rowSelectionFeature'>;\n /**\n * O que o checkbox marca e mede: as linhas da página ou todas as linhas da tabela. Com\n * paginação, a página: o checkbox fica no cabeçalho da página à vista, e marcar linhas\n * escondidas em outras surpreende. Com a paginação pela API (`manualPagination`), a tabela só\n * tem a página carregada, e `'all'` contaria os ids selecionados em outras páginas.\n * @default 'page' com `rowPaginationFeature`, 'all' sem\n */\n scope?: 'page' | 'all';\n }\n>;\n\n/**\n * O checkbox que marca ou desmarca todas as linhas, para o header de uma coluna de seleção. Com\n * parte das linhas marcadas, mostra o estado misto; o clique então marca todas. Com\n * `loadingFeature`, fica desabilitado enquanto a tabela carrega.\n *\n * As props do `Checkbox.Root` passam adiante, como `colorScheme` e `aria-label`.\n */\nexport const DataTableSelectAllCheckbox = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableSelectAllCheckboxProps<TFeatures, TData>,\n) => {\n const { table, scope, children, ...rest } = props;\n\n const isPageScope =\n scope === undefined\n ? hasTableFeature(table, 'rowPaginationFeature')\n : scope === 'page';\n\n /**\n * O estado do checkbox num valor só. Re-renderiza quando ele muda. O store, e não só o atom da\n * seleção: o resultado também muda com as linhas, como na troca de página ou de dados.\n */\n const checkedState = useSelector(table.store, () => {\n if (isPageScope) {\n return table.getIsAllPageRowsSelected()\n ? 'checked'\n : table.getIsSomePageRowsSelected()\n ? 'indeterminate'\n : 'unchecked';\n }\n\n return table.getIsAllRowsSelected()\n ? 'checked'\n : table.getIsSomeRowsSelected()\n ? 'indeterminate'\n : 'unchecked';\n });\n\n /**\n * Re-renderiza quando o carregamento liga ou desliga. A feature é opcional: assina o store. Na\n * hora, e não depois dos 200ms do visual, para não sobrar uma janela em que o clique passa.\n */\n const isLoading = useSelector(\n table.store,\n () =>\n hasTableFeature(table, 'loadingFeature') && table.atoms.isLoading.get(),\n );\n\n return (\n <Checkbox.Root\n data-component=\"DataTable.SelectAllCheckbox\"\n aria-label={\n isPageScope\n ? 'Selecionar todas as linhas da página'\n : 'Selecionar todas as linhas'\n }\n checked={checkedState === 'checked'}\n indeterminate={checkedState === 'indeterminate'}\n // Durante a carga, as linhas ainda são as antigas: marcar todas marcaria os ids delas.\n disabled={isLoading}\n onCheckedChange={(checked) =>\n isPageScope\n ? table.toggleAllPageRowsSelected(checked)\n : table.toggleAllRowsSelected(checked)\n }\n {...rest}\n >\n {children === undefined ? <Checkbox.Indicator /> : children}\n </Checkbox.Root>\n );\n};\n\nDataTableSelectAllCheckbox.displayName = 'DataTable.SelectAllCheckbox';\n"],"mappings":";;;;;;;;;;;;AAoCA,MAAa,8BAIX,UACG;CACH,MAAM,EAAE,OAAO,OAAO,UAAU,GAAG,SAAS;CAE5C,MAAM,cACJ,UAAU,KAAA,IACN,gBAAgB,OAAO,sBAAsB,IAC7C,UAAU;;;;;CAMhB,MAAM,eAAe,YAAY,MAAM,aAAa;EAClD,IAAI,aACF,OAAO,MAAM,yBAAyB,IAClC,YACA,MAAM,0BAA0B,IAC9B,kBACA;EAGR,OAAO,MAAM,qBAAqB,IAC9B,YACA,MAAM,sBAAsB,IAC1B,kBACA;CACR,CAAC;;;;;CAMD,MAAM,YAAY,YAChB,MAAM,aAEJ,gBAAgB,OAAO,gBAAgB,KAAK,MAAM,MAAM,UAAU,IAAI,CAC1E;CAEA,OACE,oBAAC,SAAS,MAAV;EACE,kBAAe;EACf,cACE,cACI,yCACA;EAEN,SAAS,iBAAiB;EAC1B,eAAe,iBAAiB;EAEhC,UAAU;EACV,kBAAkB,YAChB,cACI,MAAM,0BAA0B,OAAO,IACvC,MAAM,sBAAsB,OAAO;EAEzC,GAAI;EAEH,UAAA,aAAa,KAAA,IAAY,oBAAC,SAAS,WAAV,CAAqB,CAAA,IAAI;CACtC,CAAA;AAEnB;AAEA,2BAA2B,cAAc"}
|
|
1
|
+
{"version":3,"file":"data-table-select-all-checkbox.js","names":[],"sources":["../../../../src/components/data-table/selection/data-table-select-all-checkbox.tsx"],"sourcesContent":["import { Checkbox } from '@lucasbernardosn/react-ui/fields/checkbox';\nimport type { MergeOverride } from '@lucasbernardosn/ts-utils';\nimport { useSelector } from '@tanstack/react-store';\nimport type { RowData, TableFeatures } from '@tanstack/react-table';\nimport type { TableWith } from '../../../types';\nimport { hasTableFeature } from '../../../utils';\n\nexport type DataTableSelectAllCheckboxProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n Omit<\n Checkbox.RootProps,\n 'checked' | 'defaultChecked' | 'indeterminate' | 'onCheckedChange'\n >,\n {\n /** A tabela. Exige `rowSelectionFeature`. */\n table: TableWith<TFeatures, TData, 'rowSelectionFeature'>;\n /**\n * O que o checkbox marca e mede: as linhas da página ou todas as linhas da tabela. Com\n * paginação, a página: o checkbox fica no cabeçalho da página à vista, e marcar linhas\n * escondidas em outras surpreende. Com a paginação pela API (`manualPagination`), a tabela só\n * tem a página carregada, e `'all'` contaria os ids selecionados em outras páginas.\n * @default 'page' com `rowPaginationFeature`, 'all' sem\n */\n scope?: 'page' | 'all';\n }\n>;\n\n/**\n * O checkbox que marca ou desmarca todas as linhas, para o header de uma coluna de seleção. Com\n * parte das linhas marcadas, mostra o estado misto; o clique então marca todas. Com\n * `loadingFeature`, fica desabilitado enquanto a tabela carrega.\n *\n * As props do `Checkbox.Root` passam adiante, como `colorScheme` e `aria-label`.\n */\nexport const DataTableSelectAllCheckbox = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableSelectAllCheckboxProps<TFeatures, TData>,\n) => {\n const { table, scope, children, ...rest } = props;\n\n const isPageScope =\n scope === undefined\n ? hasTableFeature(table, 'rowPaginationFeature')\n : scope === 'page';\n\n /**\n * O estado do checkbox num valor só. Re-renderiza quando ele muda. O store, e não só o atom da\n * seleção: o resultado também muda com as linhas, como na troca de página ou de dados.\n */\n const checkedState = useSelector(table.store, () => {\n if (isPageScope) {\n return table.getIsAllPageRowsSelected()\n ? 'checked'\n : table.getIsSomePageRowsSelected()\n ? 'indeterminate'\n : 'unchecked';\n }\n\n return table.getIsAllRowsSelected()\n ? 'checked'\n : table.getIsSomeRowsSelected()\n ? 'indeterminate'\n : 'unchecked';\n });\n\n /**\n * Re-renderiza quando o carregamento liga ou desliga. A feature é opcional: assina o store. Na\n * hora, e não depois dos 200ms do visual, para não sobrar uma janela em que o clique passa.\n */\n const isLoading = useSelector(\n table.store,\n () =>\n hasTableFeature(table, 'loadingFeature') && table.atoms.isLoading.get(),\n );\n\n return (\n <Checkbox.Root\n data-component=\"DataTable.SelectAllCheckbox\"\n aria-label={\n isPageScope\n ? 'Selecionar todas as linhas da página'\n : 'Selecionar todas as linhas'\n }\n checked={checkedState === 'checked'}\n indeterminate={checkedState === 'indeterminate'}\n // Durante a carga, as linhas ainda são as antigas: marcar todas marcaria os ids delas.\n disabled={isLoading}\n onCheckedChange={(checked) =>\n isPageScope\n ? table.toggleAllPageRowsSelected(checked)\n : table.toggleAllRowsSelected(checked)\n }\n {...rest}\n >\n {children === undefined ? <Checkbox.Indicator /> : children}\n </Checkbox.Root>\n );\n};\n\nDataTableSelectAllCheckbox.displayName = 'DataTable.SelectAllCheckbox';\n"],"mappings":";;;;;;;;;;;;AAoCA,MAAa,8BAIX,UACG;CACH,MAAM,EAAE,OAAO,OAAO,UAAU,GAAG,SAAS;CAE5C,MAAM,cACJ,UAAU,KAAA,IACN,gBAAgB,OAAO,sBAAsB,IAC7C,UAAU;;;;;CAMhB,MAAM,eAAe,YAAY,MAAM,aAAa;EAClD,IAAI,aACF,OAAO,MAAM,yBAAyB,IAClC,YACA,MAAM,0BAA0B,IAC9B,kBACA;EAGR,OAAO,MAAM,qBAAqB,IAC9B,YACA,MAAM,sBAAsB,IAC1B,kBACA;CACR,CAAC;;;;;CAMD,MAAM,YAAY,YAChB,MAAM,aAEJ,gBAAgB,OAAO,gBAAgB,KAAK,MAAM,MAAM,UAAU,IAAI,CAC1E;CAEA,OACE,oBAAC,SAAS,MAAV;EACE,kBAAe;EACf,cACE,cACI,yCACA;EAEN,SAAS,iBAAiB;EAC1B,eAAe,iBAAiB;EAEhC,UAAU;EACV,kBAAkB,YAChB,cACI,MAAM,0BAA0B,OAAO,IACvC,MAAM,sBAAsB,OAAO;EAEzC,GAAI;EAEH,UAAA,aAAa,KAAA,IAAY,oBAAC,SAAS,WAAV,CAAqB,CAAA,IAAI;CACtC,CAAA;AAEnB;AAEA,2BAA2B,cAAc"}
|
|
@@ -3,7 +3,7 @@ import "../../../types/index.js";
|
|
|
3
3
|
import { RowData, TableFeatures } from "@tanstack/react-table";
|
|
4
4
|
import React from "react";
|
|
5
5
|
import { ActionBar } from "@lucasbernardosn/react-ui/overlays/action-bar";
|
|
6
|
-
import { MergeOverride } from "@lucasbernardosn/utils";
|
|
6
|
+
import { MergeOverride } from "@lucasbernardosn/ts-utils";
|
|
7
7
|
//#region src/components/data-table/selection/data-table-selection-bar.d.ts
|
|
8
8
|
export type DataTableSelectionBarProps<TFeatures extends TableFeatures, TData extends RowData> = MergeOverride<ActionBar.PopupProps, {
|
|
9
9
|
/** A tabela. Exige `rowSelectionFeature`. */
|
|
@@ -1 +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"}
|
|
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/ts-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"}
|
|
@@ -2,7 +2,7 @@ import { HeaderWith } from "../../../types/table-with.js";
|
|
|
2
2
|
import "../../../types/index.js";
|
|
3
3
|
import { RowData, TableFeatures } from "@tanstack/react-table";
|
|
4
4
|
import { useRender } from "@base-ui/react";
|
|
5
|
-
import { MergeOverride } from "@lucasbernardosn/utils";
|
|
5
|
+
import { MergeOverride } from "@lucasbernardosn/ts-utils";
|
|
6
6
|
//#region src/components/data-table/sorting/data-table-sort-indicator.d.ts
|
|
7
7
|
export type DataTableSortIndicatorProps<TFeatures extends TableFeatures, TData extends RowData> = MergeOverride<useRender.ComponentProps<'span'>, {
|
|
8
8
|
/** O header da coluna. Exige `rowSortingFeature`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table-sort-indicator.js","names":[],"sources":["../../../../src/components/data-table/sorting/data-table-sort-indicator.tsx"],"sourcesContent":["import { mergeProps, useRender } from '@base-ui/react';\nimport { Icon } from '@lucasbernardosn/react-ui/display/icon';\nimport { mergeTwClassNames } from '@lucasbernardosn/react-ui/utils';\nimport type { MergeOverride } from '@lucasbernardosn/utils';\nimport {\n CaretDownIcon,\n CaretUpDownIcon,\n CaretUpIcon,\n} from '@phosphor-icons/react';\nimport { useSelector } from '@tanstack/react-store';\nimport type { RowData, TableFeatures } from '@tanstack/react-table';\nimport type { HeaderWith } from '../../../types';\n\nexport type DataTableSortIndicatorProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n useRender.ComponentProps<'span'>,\n {\n /** O header da coluna. Exige `rowSortingFeature`. */\n header: HeaderWith<TFeatures, TData, 'rowSortingFeature'>;\n }\n>;\n\n/**\n * O ícone da direção da ordenação: seta para cima, para baixo, ou dupla e apagada com a coluna\n * fora da ordenação. Com mais de uma coluna ordenada, mostra também a posição desta. Com\n * `children`, eles substituem o ícone; a direção fica em `data-sorted`.\n *\n * Numa coluna que não ordena (`enableSorting: false`, ou sem accessor), não renderiza.\n *\n * É decorativo (`aria-hidden`): a direção chega ao leitor de tela pelo `aria-sort` do\n * `DataTable.HeaderCell`.\n */\nexport const DataTableSortIndicator = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableSortIndicatorProps<TFeatures, TData>,\n) => {\n const { header, render, className, children, ...rest } = props;\n\n const { table } = header.column;\n\n /**\n * Só re-renderiza quando a direção desta coluna muda, e só o atom da ordenação roda o seletor.\n */\n const sorted = useSelector(table.atoms.sorting, () =>\n header.column.getIsSorted(),\n );\n\n /**\n * A posição na ordenação, de 1 em diante, só com mais de uma coluna ordenada: com uma só, o\n * número não diz nada. Re-renderiza quando a posição desta coluna muda.\n */\n const position = useSelector(table.atoms.sorting, (sorting) => {\n const index = header.column.getSortIndex();\n\n return index >= 0 && sorting.length > 1 ? index + 1 : undefined;\n });\n\n const icon =\n sorted === 'asc' ? (\n <CaretUpIcon />\n ) : sorted === 'desc' ? (\n <CaretDownIcon />\n ) : (\n <CaretUpDownIcon />\n );\n\n const baseProps = {\n 'data-component': 'DataTable.SortIndicator',\n 'data-sorted': sorted || undefined,\n 'aria-hidden': true,\n className: mergeTwClassNames(\n [\n 'inline-flex',\n 'shrink-0',\n 'items-center',\n 'gap-0.5',\n\n 'text-gray-8',\n 'data-sorted:text-gray-12',\n\n 'text-2xs',\n 'tabular-nums',\n ],\n className,\n ),\n children:\n children === undefined ? (\n <>\n <Icon\n render={icon}\n className=\"size-3.5\"\n />\n {position}\n </>\n ) : (\n children\n ),\n };\n\n const element = useRender({\n render,\n defaultTagName: 'span',\n props: mergeProps(baseProps, rest),\n });\n\n return header.column.getCanSort() ? element : null;\n};\n\nDataTableSortIndicator.displayName = 'DataTable.SortIndicator';\n"],"mappings":";;;;;;;;;;;;;;;;;AAkCA,MAAa,0BAIX,UACG;CACH,MAAM,EAAE,QAAQ,QAAQ,WAAW,UAAU,GAAG,SAAS;CAEzD,MAAM,EAAE,UAAU,OAAO;;;;CAKzB,MAAM,SAAS,YAAY,MAAM,MAAM,eACrC,OAAO,OAAO,YAAY,CAC5B;;;;;CAMA,MAAM,WAAW,YAAY,MAAM,MAAM,UAAU,YAAY;EAC7D,MAAM,QAAQ,OAAO,OAAO,aAAa;EAEzC,OAAO,SAAS,KAAK,QAAQ,SAAS,IAAI,QAAQ,IAAI,KAAA;CACxD,CAAC;CAED,MAAM,OACJ,WAAW,QACT,oBAAC,aAAD,CAAc,CAAA,IACZ,WAAW,SACb,oBAAC,eAAD,CAAgB,CAAA,IAEhB,oBAAC,iBAAD,CAAkB,CAAA;CAGtB,MAAM,YAAY;EAChB,kBAAkB;EAClB,eAAe,UAAU,KAAA;EACzB,eAAe;EACf,WAAW,kBACT;GACE;GACA;GACA;GACA;GAEA;GACA;GAEA;GACA;EACF,GACA,SACF;EACA,UACE,aAAa,KAAA,IACX,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,MAAD;GACE,QAAQ;GACR,WAAU;EACX,CAAA,GACA,QACD,EAAA,CAAA,IAEF;CAEN;CAEA,MAAM,UAAU,UAAU;EACxB;EACA,gBAAgB;EAChB,OAAO,WAAW,WAAW,IAAI;CACnC,CAAC;CAED,OAAO,OAAO,OAAO,WAAW,IAAI,UAAU;AAChD;AAEA,uBAAuB,cAAc"}
|
|
1
|
+
{"version":3,"file":"data-table-sort-indicator.js","names":[],"sources":["../../../../src/components/data-table/sorting/data-table-sort-indicator.tsx"],"sourcesContent":["import { mergeProps, useRender } from '@base-ui/react';\nimport { Icon } from '@lucasbernardosn/react-ui/display/icon';\nimport { mergeTwClassNames } from '@lucasbernardosn/react-ui/utils';\nimport type { MergeOverride } from '@lucasbernardosn/ts-utils';\nimport {\n CaretDownIcon,\n CaretUpDownIcon,\n CaretUpIcon,\n} from '@phosphor-icons/react';\nimport { useSelector } from '@tanstack/react-store';\nimport type { RowData, TableFeatures } from '@tanstack/react-table';\nimport type { HeaderWith } from '../../../types';\n\nexport type DataTableSortIndicatorProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n useRender.ComponentProps<'span'>,\n {\n /** O header da coluna. Exige `rowSortingFeature`. */\n header: HeaderWith<TFeatures, TData, 'rowSortingFeature'>;\n }\n>;\n\n/**\n * O ícone da direção da ordenação: seta para cima, para baixo, ou dupla e apagada com a coluna\n * fora da ordenação. Com mais de uma coluna ordenada, mostra também a posição desta. Com\n * `children`, eles substituem o ícone; a direção fica em `data-sorted`.\n *\n * Numa coluna que não ordena (`enableSorting: false`, ou sem accessor), não renderiza.\n *\n * É decorativo (`aria-hidden`): a direção chega ao leitor de tela pelo `aria-sort` do\n * `DataTable.HeaderCell`.\n */\nexport const DataTableSortIndicator = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableSortIndicatorProps<TFeatures, TData>,\n) => {\n const { header, render, className, children, ...rest } = props;\n\n const { table } = header.column;\n\n /**\n * Só re-renderiza quando a direção desta coluna muda, e só o atom da ordenação roda o seletor.\n */\n const sorted = useSelector(table.atoms.sorting, () =>\n header.column.getIsSorted(),\n );\n\n /**\n * A posição na ordenação, de 1 em diante, só com mais de uma coluna ordenada: com uma só, o\n * número não diz nada. Re-renderiza quando a posição desta coluna muda.\n */\n const position = useSelector(table.atoms.sorting, (sorting) => {\n const index = header.column.getSortIndex();\n\n return index >= 0 && sorting.length > 1 ? index + 1 : undefined;\n });\n\n const icon =\n sorted === 'asc' ? (\n <CaretUpIcon />\n ) : sorted === 'desc' ? (\n <CaretDownIcon />\n ) : (\n <CaretUpDownIcon />\n );\n\n const baseProps = {\n 'data-component': 'DataTable.SortIndicator',\n 'data-sorted': sorted || undefined,\n 'aria-hidden': true,\n className: mergeTwClassNames(\n [\n 'inline-flex',\n 'shrink-0',\n 'items-center',\n 'gap-0.5',\n\n 'text-gray-8',\n 'data-sorted:text-gray-12',\n\n 'text-2xs',\n 'tabular-nums',\n ],\n className,\n ),\n children:\n children === undefined ? (\n <>\n <Icon\n render={icon}\n className=\"size-3.5\"\n />\n {position}\n </>\n ) : (\n children\n ),\n };\n\n const element = useRender({\n render,\n defaultTagName: 'span',\n props: mergeProps(baseProps, rest),\n });\n\n return header.column.getCanSort() ? element : null;\n};\n\nDataTableSortIndicator.displayName = 'DataTable.SortIndicator';\n"],"mappings":";;;;;;;;;;;;;;;;;AAkCA,MAAa,0BAIX,UACG;CACH,MAAM,EAAE,QAAQ,QAAQ,WAAW,UAAU,GAAG,SAAS;CAEzD,MAAM,EAAE,UAAU,OAAO;;;;CAKzB,MAAM,SAAS,YAAY,MAAM,MAAM,eACrC,OAAO,OAAO,YAAY,CAC5B;;;;;CAMA,MAAM,WAAW,YAAY,MAAM,MAAM,UAAU,YAAY;EAC7D,MAAM,QAAQ,OAAO,OAAO,aAAa;EAEzC,OAAO,SAAS,KAAK,QAAQ,SAAS,IAAI,QAAQ,IAAI,KAAA;CACxD,CAAC;CAED,MAAM,OACJ,WAAW,QACT,oBAAC,aAAD,CAAc,CAAA,IACZ,WAAW,SACb,oBAAC,eAAD,CAAgB,CAAA,IAEhB,oBAAC,iBAAD,CAAkB,CAAA;CAGtB,MAAM,YAAY;EAChB,kBAAkB;EAClB,eAAe,UAAU,KAAA;EACzB,eAAe;EACf,WAAW,kBACT;GACE;GACA;GACA;GACA;GAEA;GACA;GAEA;GACA;EACF,GACA,SACF;EACA,UACE,aAAa,KAAA,IACX,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,MAAD;GACE,QAAQ;GACR,WAAU;EACX,CAAA,GACA,QACD,EAAA,CAAA,IAEF;CAEN;CAEA,MAAM,UAAU,UAAU;EACxB;EACA,gBAAgB;EAChB,OAAO,WAAW,WAAW,IAAI;CACnC,CAAC;CAED,OAAO,OAAO,OAAO,WAAW,IAAI,UAAU;AAChD;AAEA,uBAAuB,cAAc"}
|
|
@@ -2,7 +2,7 @@ import { HeaderWith } from "../../../types/table-with.js";
|
|
|
2
2
|
import "../../../types/index.js";
|
|
3
3
|
import { RowData, TableFeatures } from "@tanstack/react-table";
|
|
4
4
|
import { useRender } from "@base-ui/react";
|
|
5
|
-
import { MergeOverride } from "@lucasbernardosn/utils";
|
|
5
|
+
import { MergeOverride } from "@lucasbernardosn/ts-utils";
|
|
6
6
|
//#region src/components/data-table/sorting/data-table-sort-trigger.d.ts
|
|
7
7
|
export type DataTableSortTriggerProps<TFeatures extends TableFeatures, TData extends RowData> = MergeOverride<useRender.ComponentProps<'button'>, {
|
|
8
8
|
/** O header da coluna. Exige `rowSortingFeature`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table-sort-trigger.js","names":[],"sources":["../../../../src/components/data-table/sorting/data-table-sort-trigger.tsx"],"sourcesContent":["import { mergeProps, type 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 { HeaderWith } from '../../../types';\nimport { DataTableHeaderButton } from '../header/data-table-header-button';\n\nexport type DataTableSortTriggerProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n useRender.ComponentProps<'button'>,\n {\n /** O header da coluna. Exige `rowSortingFeature`. */\n header: HeaderWith<TFeatures, TData, 'rowSortingFeature'>;\n }\n>;\n\n/**\n * O botão que alterna a ordenação da coluna: crescente, decrescente e sem ordenação, ou o ciclo\n * configurado nas opções da tabela. Com Shift, ordena por mais de uma coluna. Serve à ordenação\n * local (`sortedRowModel`) e à da API (`manualSorting`).\n *\n * É o `DataTable.HeaderButton` com a ação de ordenar: ocupa a célula do header, e as bordas ficam\n * com a área de agarre do `DataTable.ResizeHandle`. Os filhos são o que ele mostra, em geral o\n * `DataTable.HeaderContent` e o `DataTable.SortIndicator`. Marca a direção em `data-sorted`. Numa\n * coluna `align: 'end'`, a ordem dos filhos se inverte: o indicador vem antes do texto, e o texto\n * encosta na mesma borda dos valores.\n *\n * Numa coluna que não ordena (`enableSorting: false`, ou sem accessor), vira um `span` sem ação,\n * marcado com `data-disabled`: o layout não muda, e um controle dentro dele, como o checkbox da\n * coluna de seleção, continua clicável. Um botão desabilitado engoliria o clique.\n */\nexport const DataTableSortTrigger = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableSortTriggerProps<TFeatures, TData>,\n) => {\n const { header, render, className, ...rest } = props;\n\n /**\n * Só re-renderiza quando a direção desta coluna muda, e só o atom da ordenação roda o seletor:\n * redimensionar ou selecionar não chega aqui.\n */\n const sorted = useSelector(header.column.table.atoms.sorting, () =>\n header.column.getIsSorted(),\n );\n\n const canSort = header.column.getCanSort();\n\n const baseProps = {\n 'data-component': 'DataTable.SortTrigger',\n 'data-sorted': sorted || undefined,\n 'data-disabled': canSort ? undefined : '',\n onClick: canSort ? header.column.getToggleSortingHandler() : undefined,\n className: mergeTwClassNames(\n [\n // Invertida, a linha começa pelo fim: o texto fica na borda, e o indicador antes dele.\n 'in-data-[align=end]:flex-row-reverse',\n\n 'data-sorted:text-gray-12',\n ],\n className,\n ),\n };\n\n return (\n <DataTableHeaderButton\n {...mergeProps(baseProps, rest)}\n render={render ?? (canSort ? undefined : <span />)}\n />\n );\n};\n\nDataTableSortTrigger.displayName = 'DataTable.SortTrigger';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAkCA,MAAa,wBAIX,UACG;CACH,MAAM,EAAE,QAAQ,QAAQ,WAAW,GAAG,SAAS;;;;;CAM/C,MAAM,SAAS,YAAY,OAAO,OAAO,MAAM,MAAM,eACnD,OAAO,OAAO,YAAY,CAC5B;CAEA,MAAM,UAAU,OAAO,OAAO,WAAW;CAEzC,MAAM,YAAY;EAChB,kBAAkB;EAClB,eAAe,UAAU,KAAA;EACzB,iBAAiB,UAAU,KAAA,IAAY;EACvC,SAAS,UAAU,OAAO,OAAO,wBAAwB,IAAI,KAAA;EAC7D,WAAW,kBACT,CAEE,wCAEA,0BACF,GACA,SACF;CACF;CAEA,OACE,oBAAC,uBAAD;EACE,GAAI,WAAW,WAAW,IAAI;EAC9B,QAAQ,WAAW,UAAU,KAAA,IAAY,oBAAC,QAAD,CAAO,CAAA;CACjD,CAAA;AAEL;AAEA,qBAAqB,cAAc"}
|
|
1
|
+
{"version":3,"file":"data-table-sort-trigger.js","names":[],"sources":["../../../../src/components/data-table/sorting/data-table-sort-trigger.tsx"],"sourcesContent":["import { mergeProps, type useRender } from '@base-ui/react';\nimport { mergeTwClassNames } from '@lucasbernardosn/react-ui/utils';\nimport type { MergeOverride } from '@lucasbernardosn/ts-utils';\nimport { useSelector } from '@tanstack/react-store';\nimport type { RowData, TableFeatures } from '@tanstack/react-table';\nimport type { HeaderWith } from '../../../types';\nimport { DataTableHeaderButton } from '../header/data-table-header-button';\n\nexport type DataTableSortTriggerProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n useRender.ComponentProps<'button'>,\n {\n /** O header da coluna. Exige `rowSortingFeature`. */\n header: HeaderWith<TFeatures, TData, 'rowSortingFeature'>;\n }\n>;\n\n/**\n * O botão que alterna a ordenação da coluna: crescente, decrescente e sem ordenação, ou o ciclo\n * configurado nas opções da tabela. Com Shift, ordena por mais de uma coluna. Serve à ordenação\n * local (`sortedRowModel`) e à da API (`manualSorting`).\n *\n * É o `DataTable.HeaderButton` com a ação de ordenar: ocupa a célula do header, e as bordas ficam\n * com a área de agarre do `DataTable.ResizeHandle`. Os filhos são o que ele mostra, em geral o\n * `DataTable.HeaderContent` e o `DataTable.SortIndicator`. Marca a direção em `data-sorted`. Numa\n * coluna `align: 'end'`, a ordem dos filhos se inverte: o indicador vem antes do texto, e o texto\n * encosta na mesma borda dos valores.\n *\n * Numa coluna que não ordena (`enableSorting: false`, ou sem accessor), vira um `span` sem ação,\n * marcado com `data-disabled`: o layout não muda, e um controle dentro dele, como o checkbox da\n * coluna de seleção, continua clicável. Um botão desabilitado engoliria o clique.\n */\nexport const DataTableSortTrigger = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableSortTriggerProps<TFeatures, TData>,\n) => {\n const { header, render, className, ...rest } = props;\n\n /**\n * Só re-renderiza quando a direção desta coluna muda, e só o atom da ordenação roda o seletor:\n * redimensionar ou selecionar não chega aqui.\n */\n const sorted = useSelector(header.column.table.atoms.sorting, () =>\n header.column.getIsSorted(),\n );\n\n const canSort = header.column.getCanSort();\n\n const baseProps = {\n 'data-component': 'DataTable.SortTrigger',\n 'data-sorted': sorted || undefined,\n 'data-disabled': canSort ? undefined : '',\n onClick: canSort ? header.column.getToggleSortingHandler() : undefined,\n className: mergeTwClassNames(\n [\n // Invertida, a linha começa pelo fim: o texto fica na borda, e o indicador antes dele.\n 'in-data-[align=end]:flex-row-reverse',\n\n 'data-sorted:text-gray-12',\n ],\n className,\n ),\n };\n\n return (\n <DataTableHeaderButton\n {...mergeProps(baseProps, rest)}\n render={render ?? (canSort ? undefined : <span />)}\n />\n );\n};\n\nDataTableSortTrigger.displayName = 'DataTable.SortTrigger';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAkCA,MAAa,wBAIX,UACG;CACH,MAAM,EAAE,QAAQ,QAAQ,WAAW,GAAG,SAAS;;;;;CAM/C,MAAM,SAAS,YAAY,OAAO,OAAO,MAAM,MAAM,eACnD,OAAO,OAAO,YAAY,CAC5B;CAEA,MAAM,UAAU,OAAO,OAAO,WAAW;CAEzC,MAAM,YAAY;EAChB,kBAAkB;EAClB,eAAe,UAAU,KAAA;EACzB,iBAAiB,UAAU,KAAA,IAAY;EACvC,SAAS,UAAU,OAAO,OAAO,wBAAwB,IAAI,KAAA;EAC7D,WAAW,kBACT,CAEE,wCAEA,0BACF,GACA,SACF;CACF;CAEA,OACE,oBAAC,uBAAD;EACE,GAAI,WAAW,WAAW,IAAI;EAC9B,QAAQ,WAAW,UAAU,KAAA,IAAY,oBAAC,QAAD,CAAO,CAAA;CACjD,CAAA;AAEL;AAEA,qBAAqB,cAAc"}
|