@proef/common-ui 2.2.2 → 2.2.3

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.
@@ -16,6 +16,7 @@ function PaginatedTable({
16
16
  horizontalScrollbarBelow = true,
17
17
  skeleton = true,
18
18
  fadeRight = true,
19
+ resizableColumns = true,
19
20
  ...resto
20
21
  }) {
21
22
  const [tamanhoProprio, setTamanhoProprio] = useState(pageSize ?? pageSizeOptions?.[0] ?? 50);
@@ -34,6 +35,7 @@ function PaginatedTable({
34
35
  horizontalScrollbarBelow,
35
36
  skeleton,
36
37
  fadeRight,
38
+ resizableColumns,
37
39
  paginacaoNoTopo: {
38
40
  total,
39
41
  page,
@@ -1 +1 @@
1
- {"version":3,"file":"PaginatedTable.js","sources":["../../../../../../src/v1/components/tables/PaginatedTable/PaginatedTable.tsx"],"sourcesContent":["import React, { useState } from 'react'\r\nimport { TableBase, type TableProps } from '../Table/Table'\r\n\r\nexport interface PaginatedTableProps<T> extends TableProps<T> {\r\n /**\r\n * Total de linhas no servidor, quando é ele que pagina (`page` e\r\n * `onPageChange`). É o número da contagem e dá o número de páginas.\r\n */\r\n total?: number\r\n /**\r\n * Página atual (a contar de 1), quando é o servidor que pagina: a app pede a\r\n * página e dá-a em `data`. Sem isto, a tabela pagina-se a si mesma com todas\r\n * as linhas de `data`.\r\n */\r\n page?: number\r\n onPageChange?: (page: number) => void\r\n /** Tamanhos de página à escolha (ex: `[60, 120, 250, 500]`). Sem isto não há escolha. */\r\n pageSizeOptions?: number[]\r\n /**\r\n * A pessoa escolheu outro tamanho de página. Quando é o servidor que pagina,\r\n * a app volta à página 1 (ficar na 7.ª com 500 por página caía fora da lista).\r\n * Sem isto, a tabela guarda a escolha ela própria.\r\n */\r\n onPageSizeChange?: (pageSize: number) => void\r\n}\r\n\r\n/**\r\n * A [Table](?path=/docs/v1-components-tables-table--docs) para listas de página inteira: a paginação fica EM CIMA, numa\r\n * barra com a contagem de linhas, o tamanho de página e os números de página,\r\n * em vez de no fundo.\r\n *\r\n * Funciona de duas maneiras:\r\n * - **O servidor pagina** (`page`, `onPageChange`, `total`): `data` é a\r\n * página atual. Com filtros, ordenação ou agrupamento no cabeçalho, a tabela\r\n * passa a paginar o conjunto completo (`allData`) e a barra mostra as\r\n * páginas dela.\r\n * - **Todas as linhas de uma vez** (só `data`): a tabela pagina-se a si mesma.\r\n *\r\n * Por omissão ocupa a altura do pai (`fillHeight`), com as barras de scroll\r\n * por cima das linhas, linhas-esqueleto a carregar e a aresta direita\r\n * esbatida. Qualquer uma pode ser desligada.\r\n */\r\nexport default function PaginatedTable<T>({\r\n total,\r\n page,\r\n onPageChange,\r\n pageSizeOptions,\r\n onPageSizeChange,\r\n pageSize,\r\n data,\r\n allData,\r\n alwaysClient,\r\n fillHeight = true,\r\n overlayScrollbars = true,\r\n horizontalScrollbarBelow = true,\r\n skeleton = true,\r\n fadeRight = true,\r\n ...resto\r\n}: PaginatedTableProps<T>) {\r\n const [tamanhoProprio, setTamanhoProprio] = useState(pageSize ?? pageSizeOptions?.[0] ?? 50)\r\n const tamanho = onPageSizeChange ? (pageSize ?? pageSizeOptions?.[0] ?? 50) : tamanhoProprio\r\n // Sem paginação do servidor, todas as linhas são o conjunto completo e a tabela pagina-as.\r\n const peloServidor = !!onPageChange && page !== undefined\r\n return (\r\n <TableBase\r\n {...resto}\r\n data={data}\r\n allData={peloServidor ? allData : (allData ?? data)}\r\n alwaysClient={peloServidor ? alwaysClient : true}\r\n pageSize={tamanho}\r\n fillHeight={fillHeight}\r\n overlayScrollbars={overlayScrollbars}\r\n horizontalScrollbarBelow={horizontalScrollbarBelow}\r\n skeleton={skeleton}\r\n fadeRight={fadeRight}\r\n paginacaoNoTopo={{\r\n total,\r\n page,\r\n onPageChange,\r\n pageSizeOptions,\r\n onPageSizeChange: onPageSizeChange ?? (pageSizeOptions ? setTamanhoProprio : undefined),\r\n }}\r\n />\r\n )\r\n}\r\n"],"names":[],"mappings":";;;AA0CA,SAAwB,eAAkB;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb,oBAAoB;AAAA,EACpB,2BAA2B;AAAA,EAC3B,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,GAAG;AACL,GAA2B;AACzB,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAS,YAAY,kBAAkB,CAAC,KAAK,EAAE;AAC3F,QAAM,UAAU,mBAAoB,YAAY,kBAAkB,CAAC,KAAK,KAAM;AAE9E,QAAM,eAAe,CAAC,CAAC,gBAAgB,SAAS;AAChD,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACE,GAAG;AAAA,MACJ;AAAA,MACA,SAAS,eAAe,UAAW,WAAW;AAAA,MAC9C,cAAc,eAAe,eAAe;AAAA,MAC5C,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,iBAAiB;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,kBAAkB,qBAAqB,kBAAkB,oBAAoB;AAAA,MAAA;AAAA,IAC/E;AAAA,EAAA;AAGN;"}
1
+ {"version":3,"file":"PaginatedTable.js","sources":["../../../../../../src/v1/components/tables/PaginatedTable/PaginatedTable.tsx"],"sourcesContent":["import React, { useState } from 'react'\r\nimport { TableBase, type TableProps } from '../Table/Table'\r\n\r\nexport interface PaginatedTableProps<T> extends TableProps<T> {\r\n /**\r\n * Total de linhas no servidor, quando é ele que pagina (`page` e\r\n * `onPageChange`). É o número da contagem e dá o número de páginas.\r\n */\r\n total?: number\r\n /**\r\n * Página atual (a contar de 1), quando é o servidor que pagina: a app pede a\r\n * página e dá-a em `data`. Sem isto, a tabela pagina-se a si mesma com todas\r\n * as linhas de `data`.\r\n */\r\n page?: number\r\n onPageChange?: (page: number) => void\r\n /** Tamanhos de página à escolha (ex: `[60, 120, 250, 500]`). Sem isto não há escolha. */\r\n pageSizeOptions?: number[]\r\n /**\r\n * A pessoa escolheu outro tamanho de página. Quando é o servidor que pagina,\r\n * a app volta à página 1 (ficar na 7.ª com 500 por página caía fora da lista).\r\n * Sem isto, a tabela guarda a escolha ela própria.\r\n */\r\n onPageSizeChange?: (pageSize: number) => void\r\n}\r\n\r\n/**\r\n * A [Table](?path=/docs/v1-components-tables-table--docs) para listas de página inteira: a paginação fica EM CIMA, numa\r\n * barra com a contagem de linhas, o tamanho de página e os números de página,\r\n * em vez de no fundo.\r\n *\r\n * Funciona de duas maneiras:\r\n * - **O servidor pagina** (`page`, `onPageChange`, `total`): `data` é a\r\n * página atual. Com filtros, ordenação ou agrupamento no cabeçalho, a tabela\r\n * passa a paginar o conjunto completo (`allData`) e a barra mostra as\r\n * páginas dela.\r\n * - **Todas as linhas de uma vez** (só `data`): a tabela pagina-se a si mesma.\r\n *\r\n * Por omissão ocupa a altura do pai (`fillHeight`), com as barras de scroll\r\n * por cima das linhas, linhas-esqueleto a carregar e a aresta direita\r\n * esbatida, e as colunas redimensionáveis. Qualquer uma pode ser desligada.\r\n */\r\nexport default function PaginatedTable<T>({\r\n total,\r\n page,\r\n onPageChange,\r\n pageSizeOptions,\r\n onPageSizeChange,\r\n pageSize,\r\n data,\r\n allData,\r\n alwaysClient,\r\n fillHeight = true,\r\n overlayScrollbars = true,\r\n horizontalScrollbarBelow = true,\r\n skeleton = true,\r\n fadeRight = true,\r\n resizableColumns = true,\r\n ...resto\r\n}: PaginatedTableProps<T>) {\r\n const [tamanhoProprio, setTamanhoProprio] = useState(pageSize ?? pageSizeOptions?.[0] ?? 50)\r\n const tamanho = onPageSizeChange ? (pageSize ?? pageSizeOptions?.[0] ?? 50) : tamanhoProprio\r\n // Sem paginação do servidor, todas as linhas são o conjunto completo e a tabela pagina-as.\r\n const peloServidor = !!onPageChange && page !== undefined\r\n return (\r\n <TableBase\r\n {...resto}\r\n data={data}\r\n allData={peloServidor ? allData : (allData ?? data)}\r\n alwaysClient={peloServidor ? alwaysClient : true}\r\n pageSize={tamanho}\r\n fillHeight={fillHeight}\r\n overlayScrollbars={overlayScrollbars}\r\n horizontalScrollbarBelow={horizontalScrollbarBelow}\r\n skeleton={skeleton}\r\n fadeRight={fadeRight}\r\n resizableColumns={resizableColumns}\r\n paginacaoNoTopo={{\r\n total,\r\n page,\r\n onPageChange,\r\n pageSizeOptions,\r\n onPageSizeChange: onPageSizeChange ?? (pageSizeOptions ? setTamanhoProprio : undefined),\r\n }}\r\n />\r\n )\r\n}\r\n"],"names":[],"mappings":";;;AA0CA,SAAwB,eAAkB;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb,oBAAoB;AAAA,EACpB,2BAA2B;AAAA,EAC3B,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,mBAAmB;AAAA,EACnB,GAAG;AACL,GAA2B;AACzB,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAS,YAAY,kBAAkB,CAAC,KAAK,EAAE;AAC3F,QAAM,UAAU,mBAAoB,YAAY,kBAAkB,CAAC,KAAK,KAAM;AAE9E,QAAM,eAAe,CAAC,CAAC,gBAAgB,SAAS;AAChD,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACE,GAAG;AAAA,MACJ;AAAA,MACA,SAAS,eAAe,UAAW,WAAW;AAAA,MAC9C,cAAc,eAAe,eAAe;AAAA,MAC5C,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,iBAAiB;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,kBAAkB,qBAAqB,kBAAkB,oBAAoB;AAAA,MAAA;AAAA,IAC/E;AAAA,EAAA;AAGN;"}
@@ -53,6 +53,7 @@ function TableBase({
53
53
  headerRowClassName: classeCabecalho = "bg-slate-50",
54
54
  scrollbarOnEdge: barraNaBorda = true,
55
55
  bordered: comCaixa = false,
56
+ resizableColumns: redimensionavel = false,
56
57
  horizontalScrollbarBelow: barraHorizontalFora = false,
57
58
  skeleton: esqueletoAoCarregar = false,
58
59
  fadeRight: esbaterDireita = false,
@@ -886,6 +887,41 @@ function TableBase({
886
887
  ro.observe(c);
887
888
  return () => ro.disconnect();
888
889
  }, [preencheAltura, paginatedData]);
890
+ const redimensionar = useRef(null);
891
+ const MIN_LARGURA = 48;
892
+ const pegaRedimensionar = (chave) => redimensionavel && larguras ? /* @__PURE__ */ jsx(
893
+ "span",
894
+ {
895
+ role: "separator",
896
+ "aria-orientation": "vertical",
897
+ title: L.resizeColumn,
898
+ onPointerDown: (e) => {
899
+ e.stopPropagation();
900
+ e.preventDefault();
901
+ e.currentTarget.setPointerCapture?.(e.pointerId);
902
+ const th = e.currentTarget.parentElement;
903
+ redimensionar.current = { chave, x: e.clientX, largura: th.getBoundingClientRect().width };
904
+ },
905
+ onPointerMove: (e) => {
906
+ const r = redimensionar.current;
907
+ if (!r) return;
908
+ const nova = Math.max(MIN_LARGURA, Math.round(r.largura + e.clientX - r.x));
909
+ setLarguras((l) => l ? { ...l, [r.chave]: nova } : l);
910
+ },
911
+ onPointerUp: () => {
912
+ redimensionar.current = null;
913
+ },
914
+ onPointerCancel: () => {
915
+ redimensionar.current = null;
916
+ },
917
+ onClick: (e) => e.stopPropagation(),
918
+ onDoubleClick: (e) => {
919
+ e.stopPropagation();
920
+ setLarguras(null);
921
+ },
922
+ className: "absolute right-0 top-0 z-[5] h-full w-1.5 cursor-col-resize touch-none bg-transparent transition-colors hover:bg-primary/40"
923
+ }
924
+ ) : null;
889
925
  const grupoColunas = largurasVista ? /* @__PURE__ */ jsx("colgroup", { children: chavesVista.map((k) => /* @__PURE__ */ jsx("col", { style: { width: largurasVista[k] } }, k)) }) : null;
890
926
  const estiloTabela = largurasVista ? { tableLayout: "fixed", width: chavesVista.reduce((a, k) => a + (largurasVista[k] ?? 0), 0), minWidth: "100%" } : { width: "max-content" };
891
927
  const cabecalho = (fixoNoTopo) => /* @__PURE__ */ jsx("thead", { className: fixoNoTopo ? "sticky top-0 z-20" : void 0, children: /* @__PURE__ */ jsxs("tr", { ref: cabecalhoRef, className: `text-micro font-black uppercase text-slate-400 tracking-[0.15em] ${!bordasSeparadas ? "border-b-2 border-slate-200 bg-slate-50" : fundoNosTitulos ? "[&>th]:border-b-2 [&>th]:border-slate-200" : "shadow-[inset_0_-2px_0_0_var(--color-slate-200)]"}`, children: [
@@ -904,7 +940,7 @@ function TableBase({
904
940
  {
905
941
  style: cabecaFixa(i + (selectable ? 1 : 0)).style,
906
942
  onPointerDown: arrastavel ? (e) => premirTitulo(e, col.key) : void 0,
907
- className: `px-4 py-3 ${col.headerClassName ?? ""} ${cabecaFixa(i + (selectable ? 1 : 0)).className} ${arrastavel ? "cursor-grab" : ""} ${realce(col.key, true)} ${transicaoRealce}`,
943
+ className: `px-4 py-3 ${cabecaFixa(i + (selectable ? 1 : 0)).style ? "" : "relative"} ${col.headerClassName ?? ""} ${cabecaFixa(i + (selectable ? 1 : 0)).className} ${arrastavel ? "cursor-grab" : ""} ${realce(col.key, true)} ${transicaoRealce}`,
908
944
  "data-col": col.key,
909
945
  children: [
910
946
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 group/hdr whitespace-nowrap select-none", children: [
@@ -913,12 +949,16 @@ function TableBase({
913
949
  {
914
950
  onClick: () => {
915
951
  if (!allData) onDataNeeded?.();
916
- if (sortCol === col.key) setSortDir((d) => d === "asc" ? "desc" : "asc");
952
+ if (sortCol === col.key && sortDir === "desc") {
953
+ setSortCol(defaultSortCol ?? null);
954
+ setSortDir(defaultSortDir ?? "asc");
955
+ } else if (sortCol === col.key) setSortDir("desc");
917
956
  else {
918
957
  setSortCol(col.key);
919
958
  setSortDir("asc");
920
959
  }
921
960
  },
961
+ title: isSortActive && sortDir === "desc" ? L.resetSort : void 0,
922
962
  className: `flex items-center gap-0.5 transition-colors hover:text-slate-700 ${isSortActive ? "text-proef-blue" : ""}`,
923
963
  children: [
924
964
  /* @__PURE__ */ jsx("span", { children: col.label }),
@@ -972,8 +1012,13 @@ function TableBase({
972
1012
  ordenadaPor: sortCol === col.key ? sortDir : null,
973
1013
  aCarregar: !allData && !!isAllDataLoading,
974
1014
  onOrdenar: (dir) => {
975
- setSortCol(col.key);
976
- setSortDir(dir);
1015
+ if (sortCol === col.key && sortDir === dir) {
1016
+ setSortCol(defaultSortCol ?? null);
1017
+ setSortDir(defaultSortDir ?? "asc");
1018
+ } else {
1019
+ setSortCol(col.key);
1020
+ setSortDir(dir);
1021
+ }
977
1022
  },
978
1023
  onAplicar: (vals) => {
979
1024
  aplicarValores(col.key, vals);
@@ -1055,7 +1100,8 @@ function TableBase({
1055
1100
  ] }, sf.key);
1056
1101
  })
1057
1102
  ] }),
1058
- col.headerExtra && /* @__PURE__ */ jsx("div", { className: "mt-0.5 normal-case font-normal tracking-normal", children: col.headerExtra(filteredData) })
1103
+ col.headerExtra && /* @__PURE__ */ jsx("div", { className: "mt-0.5 normal-case font-normal tracking-normal", children: col.headerExtra(filteredData) }),
1104
+ pegaRedimensionar(col.key)
1059
1105
  ]
1060
1106
  },
1061
1107
  col.key