@proef/common-ui 2.2.0 → 2.2.2
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/dist/esm/index.js +26 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/legacy/components/molecules/DataTable/DataTable.js +1 -1
- package/dist/esm/legacy/components/molecules/DataTable/DataTable.js.map +1 -1
- package/dist/esm/v1/components/lists/ListFinder/ListFinder.js +111 -54
- package/dist/esm/v1/components/lists/ListFinder/ListFinder.js.map +1 -1
- package/dist/esm/v1/components/tables/Table/ColumnFilter.js +14 -14
- package/dist/esm/v1/components/tables/Table/ColumnFilter.js.map +1 -1
- package/dist/esm/v1/components/tables/Table/Table.js +9 -8
- package/dist/esm/v1/components/tables/Table/Table.js.map +1 -1
- package/dist/esm/v1/foundations/icons/icons.js +49 -0
- package/dist/esm/v1/foundations/icons/icons.js.map +1 -1
- package/dist/esm/v1/primitives/display/RichText/RichText.js +12 -0
- package/dist/esm/v1/primitives/display/RichText/RichText.js.map +1 -0
- package/dist/esm/v1/primitives/display/RichText/utils.js +56 -0
- package/dist/esm/v1/primitives/display/RichText/utils.js.map +1 -0
- package/dist/esm/v1/primitives/forms/RichTextEditor/RichTextEditor.js +253 -0
- package/dist/esm/v1/primitives/forms/RichTextEditor/RichTextEditor.js.map +1 -0
- package/dist/esm/v1/primitives/lists/ListItem/ListItem.js +45 -11
- package/dist/esm/v1/primitives/lists/ListItem/ListItem.js.map +1 -1
- package/dist/style.components.css +1 -1
- package/dist/style.css +1 -1
- package/dist/style.layered.css +1 -1
- package/dist/types/v1/components/lists/ListFinder/ListFinder.d.ts +31 -5
- package/dist/types/v1/components/tables/Table/Table.d.ts +9 -1
- package/dist/types/v1/foundations/icons/icons.d.ts +20 -0
- package/dist/types/v1/index.d.ts +8 -3
- package/dist/types/v1/primitives/display/RichText/RichText.d.ts +17 -0
- package/dist/types/v1/primitives/display/RichText/utils.d.ts +22 -0
- package/dist/types/v1/primitives/forms/RichTextEditor/RichTextEditor.d.ts +64 -0
- package/dist/types/v1/primitives/lists/ListItem/ListItem.d.ts +39 -8
- package/package.json +6 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ColumnFilter.js","sources":["../../../../../../src/v1/components/tables/Table/ColumnFilter.tsx"],"sourcesContent":["import React, { useEffect, useId, useMemo, useRef, useState } from 'react'\r\nimport { createPortal } from 'react-dom'\r\nimport { CheckIcon, ChevronDownIcon, ChevronUpIcon, ListIcon, SlidersIcon } from '../../../foundations/icons/icons'\r\nimport type { TableLabels } from './labels'\r\n\r\n/** Onde o popup abre e quanto pode crescer. */\r\nconst ALTURA = 420\r\nconst LARGURA = 320\r\n\r\n/**\r\n * O filtro de uma coluna: ordenar, procurar, escolher valores, aplicar.\r\n *\r\n * Vive fora do `Table` de propósito. Lá dentro era uma função declarada no\r\n * corpo do componente, logo uma função NOVA a cada render — e o React\r\n * desmontava e remontava o popup a cada tecla escrita e a cada opção marcada.\r\n * Era isso que devolvia a lista de valores ao topo a meio de uma escolha.\r\n *\r\n * Nada se aplica até ao \"Aplicar\". Com a aplicação imediata, cada visto refazia\r\n * a tabela por baixo: mudava-lhe o tamanho e o conteúdo enquanto se escolhia, e\r\n * a lista de onde se estava a escolher encolhia à medida que se escolhia.\r\n *\r\n * `position: fixed` no `<body>`: como filho da célula, o `overflow` da tabela\r\n * cortava-o — e era por isso que a caixa da tabela tinha de perder o tecto de\r\n * altura enquanto um filtro estivesse aberto, o que empurrava a página inteira.\r\n */\r\nexport function ColumnFilter({\r\n labels: L, label, canSort, tipo, valores, seleccionados, intervalo, numero, ordenadaPor, aCarregar, ancora,\r\n onOrdenar, onAplicar, onAplicarDatas, onAplicarNumeros, onLimpar, onFechar,\r\n}: {\r\n labels: TableLabels\r\n label?: string\r\n canSort?: boolean\r\n /** `texto` = lista de valores; `data` = De/Até; `numero` = Mín/Máx, ou a lista (botão no topo). */\r\n tipo: 'texto' | 'data' | 'numero'\r\n /** Valores distintos da coluna, já contados com os outros filtros activos. */\r\n valores: string[]\r\n /** O que está aplicado neste momento — o ponto de partida do rascunho. */\r\n seleccionados: Set<string>\r\n intervalo: { from?: string; to?: string }\r\n /** Intervalo numérico aplicado, quando `tipo` é `numero`. */\r\n numero?: { min?: string; max?: string }\r\n ordenadaPor: 'asc' | 'desc' | null\r\n aCarregar: boolean\r\n /** Rect do botão que abriu isto. */\r\n ancora: DOMRect\r\n onOrdenar?: (dir: 'asc' | 'desc') => void\r\n onAplicar: (vals: Set<string>) => void\r\n onAplicarDatas?: (de: string, ate: string) => void\r\n onAplicarNumeros?: (min: string, max: string) => void\r\n onLimpar: () => void\r\n onFechar: () => void\r\n}) {\r\n const caixa = useRef<HTMLDivElement>(null)\r\n const idMin = useId()\r\n const [busca, setBusca] = useState('')\r\n /** O que está escolhido AGORA, sem ter saído daqui. Só o \"Aplicar\" o leva lá fora. */\r\n const [rascunho, setRascunho] = useState<Set<string>>(() => new Set(seleccionados))\r\n const [de, setDe] = useState(intervalo.from ?? '')\r\n const [ate, setAte] = useState(intervalo.to ?? '')\r\n const [min, setMin] = useState(numero?.min ?? '')\r\n const [max, setMax] = useState(numero?.max ?? '')\r\n /* Numa coluna de números, Mín/Máx ou a lista de valores. Abre na lista, salvo\r\n se já houver Mín/Máx aplicado: quem filtrou por intervalo e volta a abrir\r\n quer ver o intervalo. */\r\n const [modoLista, setModoLista] = useState(tipo === 'numero' && !numero?.min && !numero?.max)\r\n const lista = tipo === 'texto' || (tipo === 'numero' && modoLista)\r\n\r\n const visiveis = useMemo(() => {\r\n const achados = valores.filter(v => v.toLowerCase().includes(busca.toLowerCase()))\r\n // Por valor e não por texto: \"10\" antes de \"2\" numa lista de números é ruído.\r\n if (tipo !== 'numero') return achados\r\n return [...achados].sort((a, b) => {\r\n const na = Number(a), nb = Number(b)\r\n const va = a !== '—' && Number.isFinite(na), vb = b !== '—' && Number.isFinite(nb)\r\n if (va && vb) return na - nb\r\n return va ? -1 : vb ? 1 : a.localeCompare(b)\r\n })\r\n }, [valores, busca, tipo])\r\n const todosVisiveis = visiveis.length > 0 && visiveis.every(v => rascunho.has(v))\r\n const algunsVisiveis = visiveis.some(v => rascunho.has(v)) && !todosVisiveis\r\n\r\n /**\r\n * Marca ou desmarca os valores À VISTA — os que a pesquisa deixou passar.\r\n *\r\n * Com pesquisa activa, \"tudo\" é o que está no ecrã: escolher de uma vez os\r\n * valores que começam por \"Norte\" é o gesto que isto serve, e mexer nos\r\n * outros quarenta por baixo era o contrário do que se pediu.\r\n */\r\n const alternarTodos = () => setRascunho(prev => {\r\n const n = new Set(prev)\r\n if (todosVisiveis) for (const v of visiveis) n.delete(v)\r\n else for (const v of visiveis) n.add(v)\r\n return n\r\n })\r\n\r\n const alternar = (v: string) => setRascunho(prev => {\r\n const n = new Set(prev)\r\n if (n.has(v)) n.delete(v)\r\n else n.add(v)\r\n return n\r\n })\r\n\r\n const mesmoConjunto = (a: Set<string>, b: Set<string>) =>\r\n a.size === b.size && [...a].every(v => b.has(v))\r\n const sujo = tipo === 'data'\r\n ? de !== (intervalo.from ?? '') || ate !== (intervalo.to ?? '')\r\n : tipo === 'numero' && !modoLista\r\n ? min !== (numero?.min ?? '') || max !== (numero?.max ?? '')\r\n : !mesmoConjunto(rascunho, seleccionados)\r\n const temFiltro = seleccionados.size > 0 || !!intervalo.from || !!intervalo.to || !!numero?.min || !!numero?.max\r\n\r\n useEffect(() => {\r\n const fora = (e: MouseEvent) => {\r\n if (caixa.current && !caixa.current.contains(e.target as Node)) onFechar()\r\n }\r\n const tecla = (e: KeyboardEvent) => { if (e.key === 'Escape') onFechar() }\r\n /*\r\n Rolar FORA fecha; rolar DENTRO da lista não.\r\n A caixa está presa a coordenadas do ecrã, logo tem de fechar quando a\r\n página se move por baixo dela — mas a própria lista rola (podem ser\r\n dezenas de valores), e o `capture` também apanha esse.\r\n */\r\n const aoRolar = (e: Event) => {\r\n if (caixa.current && e.target instanceof Node && caixa.current.contains(e.target)) return\r\n onFechar()\r\n }\r\n document.addEventListener('mousedown', fora)\r\n document.addEventListener('keydown', tecla)\r\n window.addEventListener('scroll', aoRolar, true)\r\n window.addEventListener('resize', onFechar)\r\n return () => {\r\n document.removeEventListener('mousedown', fora)\r\n document.removeEventListener('keydown', tecla)\r\n window.removeEventListener('scroll', aoRolar, true)\r\n window.removeEventListener('resize', onFechar)\r\n }\r\n }, [onFechar])\r\n\r\n /* Troca Mín/Máx ↔ lista. Vai na linha que já existe (a do \"Mínimo\", ou a da\r\n pesquisa) e não numa só para ele: uma linha inteira para um botão pequeno\r\n era espaço vazio à esquerda. */\r\n const botaoModo = tipo === 'numero' && (\r\n <button\r\n type=\"button\"\r\n onClick={e => { e.preventDefault(); setModoLista(m => !m) }}\r\n title={modoLista ? L.showRange : L.showList}\r\n className=\"inline-flex items-center gap-1 text-[9px] font-black uppercase tracking-widest text-slate-400 hover:text-proef-blue flex-shrink-0 whitespace-nowrap\"\r\n >\r\n {modoLista ? <SlidersIcon size={10} /> : <ListIcon size={10} />}\r\n {modoLista ? L.showRange : L.showList}\r\n </button>\r\n )\r\n\r\n // Abre para cima quando não há espaço por baixo — nas colunas da direita e\r\n // com a janela baixa, o que ficava de fora eram os botões de aplicar.\r\n const paraCima = window.innerHeight - ancora.bottom < ALTURA && ancora.top > ALTURA\r\n\r\n return createPortal(\r\n <div\r\n ref={caixa}\r\n style={{\r\n position: 'fixed',\r\n left: Math.max(4, Math.min(ancora.left, window.innerWidth - LARGURA - 4)),\r\n ...(paraCima ? { bottom: window.innerHeight - ancora.top + 2 } : { top: ancora.bottom + 2 }),\r\n width: LARGURA,\r\n maxHeight: ALTURA,\r\n }}\r\n className=\"v1-reset z-[250] flex flex-col bg-white border border-slate-200 shadow-lg\"\r\n >\r\n {label && (\r\n <div className=\"px-3 pt-2.5 pb-2 border-b border-slate-100 flex-shrink-0\">\r\n <span className=\"text-[9px] font-black uppercase tracking-widest text-proef-blue\">{label}</span>\r\n </div>\r\n )}\r\n {aCarregar && (\r\n <div className=\"px-3 py-1.5 bg-amber-50 border-b border-amber-100 flex items-center gap-1.5 text-micro text-amber-700 flex-shrink-0\">\r\n <span aria-hidden className=\"inline-block h-2.5 w-2.5 animate-spin rounded-full border-2 border-current border-t-transparent \" />\r\n {L.loadingOptions}\r\n </div>\r\n )}\r\n {canSort && onOrdenar && (\r\n <div className=\"border-b border-slate-100 p-1.5 space-y-0.5 flex-shrink-0\">\r\n <button\r\n onClick={() => onOrdenar('asc')}\r\n className={`w-full flex items-center gap-2 px-2.5 py-1.5 text-caption font-semibold text-left hover:bg-slate-50 transition-colors ${ordenadaPor === 'asc' ? 'text-proef-blue bg-slate-50' : 'text-slate-600'}`}\r\n >\r\n <ChevronUpIcon size={11} /> {tipo === 'data' ? L.sortDateAsc : tipo === 'numero' ? L.sortNumAsc : L.sortAsc}\r\n </button>\r\n <button\r\n onClick={() => onOrdenar('desc')}\r\n className={`w-full flex items-center gap-2 px-2.5 py-1.5 text-caption font-semibold text-left hover:bg-slate-50 transition-colors ${ordenadaPor === 'desc' ? 'text-proef-blue bg-slate-50' : 'text-slate-600'}`}\r\n >\r\n <ChevronDownIcon size={11} /> {tipo === 'data' ? L.sortDateDesc : tipo === 'numero' ? L.sortNumDesc : L.sortDesc}\r\n </button>\r\n </div>\r\n )}\r\n\r\n {tipo === 'data' ? (\r\n <div className=\"p-3 space-y-2\">\r\n <label className=\"block\">\r\n <span className=\"text-[9px] font-black uppercase tracking-widest text-slate-400\">{L.dateFrom}</span>\r\n <input\r\n type=\"date\" value={de} onChange={e => setDe(e.target.value)}\r\n onKeyDown={e => { if (e.key === 'Enter') onAplicarDatas?.(de, ate) }}\r\n className=\"w-full mt-0.5 bg-slate-50 border border-slate-100 px-2.5 py-1.5 text-xs outline-none focus:border-proef-blue\"\r\n />\r\n </label>\r\n <label className=\"block\">\r\n <span className=\"text-[9px] font-black uppercase tracking-widest text-slate-400\">{L.dateTo}</span>\r\n <input\r\n type=\"date\" value={ate} onChange={e => setAte(e.target.value)}\r\n onKeyDown={e => { if (e.key === 'Enter') onAplicarDatas?.(de, ate) }}\r\n className=\"w-full mt-0.5 bg-slate-50 border border-slate-100 px-2.5 py-1.5 text-xs outline-none focus:border-proef-blue\"\r\n />\r\n </label>\r\n </div>\r\n ) : !lista ? (\r\n /* Mín/Máx em vez da lista: numa coluna de dinheiro ou de contagem há\r\n tantos valores distintos quantas as linhas, e ninguém procura \"10.04\".\r\n Vazio de um dos lados vale \"sem limite desse lado\". */\r\n <div className=\"p-3 space-y-2\">\r\n {/* O botão da lista fica FORA da etiqueta: dentro dela, era o botão\r\n (e não a caixa) que recebia o nome \"Mínimo\", e a caixa ficava sem\r\n nome nenhum para os leitores de ecrã. */}\r\n <div>\r\n <span className=\"flex items-center justify-between\">\r\n <label htmlFor={idMin} className=\"text-[9px] font-black uppercase tracking-widest text-slate-400\">{L.min}</label>\r\n {botaoModo}\r\n </span>\r\n <input\r\n id={idMin}\r\n type=\"number\" value={min} onChange={e => setMin(e.target.value)}\r\n onKeyDown={e => { if (e.key === 'Enter') onAplicarNumeros?.(min, max) }}\r\n className=\"w-full mt-0.5 bg-slate-50 border border-slate-100 px-2.5 py-1.5 text-xs outline-none focus:border-proef-blue\"\r\n />\r\n </div>\r\n <label className=\"block\">\r\n <span className=\"text-[9px] font-black uppercase tracking-widest text-slate-400\">{L.max}</span>\r\n <input\r\n type=\"number\" value={max} onChange={e => setMax(e.target.value)}\r\n onKeyDown={e => { if (e.key === 'Enter') onAplicarNumeros?.(min, max) }}\r\n className=\"w-full mt-0.5 bg-slate-50 border border-slate-100 px-2.5 py-1.5 text-xs outline-none focus:border-proef-blue\"\r\n />\r\n </label>\r\n </div>\r\n ) : (\r\n <>\r\n <div className=\"p-1.5 flex-shrink-0 flex items-center gap-2\">\r\n <input\r\n autoFocus type=\"text\" value={busca} onChange={e => setBusca(e.target.value)} placeholder={L.search}\r\n className=\"flex-1 min-w-0 bg-slate-50 border border-slate-100 px-2.5 py-1.5 text-xs outline-none focus:border-proef-blue\"\r\n />\r\n {botaoModo && <span className=\"pr-1.5\">{botaoModo}</span>}\r\n </div>\r\n {/* \"Tudo\" à cabeça da lista, como no Excel: marcar tudo e tirar o que\r\n não se quer é mais rápido do que marcar quarenta à mão. */}\r\n {visiveis.length > 0 && (\r\n <button\r\n onClick={alternarTodos}\r\n className=\"flex items-center gap-2 px-3 py-1.5 border-y border-slate-100 hover:bg-slate-50 text-left flex-shrink-0\"\r\n >\r\n <div className={`w-3.5 h-3.5 flex items-center justify-center border flex-shrink-0 transition-colors ${\r\n todosVisiveis ? 'bg-primary border-primary'\r\n : algunsVisiveis ? 'bg-primary/30 border-primary'\r\n : 'border-slate-300'\r\n }`}>\r\n {todosVisiveis && <CheckIcon size={9} strokeWidth={3} className=\"text-white\" />}\r\n </div>\r\n <span className=\"text-caption font-semibold text-slate-600\">\r\n {busca ? L.selectAllFound(visiveis.length) : L.selectAll}\r\n </span>\r\n </button>\r\n )}\r\n <div className=\"flex-1 overflow-y-auto p-1.5 space-y-0.5 min-h-0\">\r\n {visiveis.length === 0\r\n ? <p className=\"text-caption text-slate-400 text-center py-3\">{L.noResults}</p>\r\n : visiveis.map(v => {\r\n const escolhido = rascunho.has(v)\r\n return (\r\n <button key={v} onClick={() => alternar(v)} className=\"w-full flex items-center gap-2 px-2 py-1.5 hover:bg-slate-50 text-left\">\r\n <div className={`w-3.5 h-3.5 flex items-center justify-center border flex-shrink-0 transition-colors ${escolhido ? 'bg-primary border-primary' : 'border-slate-300'}`}>\r\n {escolhido && <CheckIcon size={9} strokeWidth={3} className=\"text-white\" />}\r\n </div>\r\n <span className=\"text-xs text-slate-700 whitespace-normal break-words leading-snug\">{v}</span>\r\n </button>\r\n )\r\n })}\r\n </div>\r\n </>\r\n )}\r\n\r\n {/* Aplicar/Cancelar fora da zona que rola, sempre à vista: são eles que\r\n dizem que ainda não aconteceu nada. */}\r\n <div className=\"flex items-center gap-1.5 p-1.5 border-t border-slate-100 flex-shrink-0 bg-white\">\r\n <button\r\n onClick={() => {\r\n if (tipo === 'data') onAplicarDatas?.(de, ate)\r\n else if (tipo === 'numero' && !modoLista) onAplicarNumeros?.(min, max)\r\n else onAplicar(rascunho)\r\n }}\r\n disabled={!sujo}\r\n className=\"flex-1 text-micro font-black uppercase tracking-wider text-white bg-primary hover:bg-primary/90 py-1.5 disabled:opacity-30\"\r\n >\r\n {L.apply}\r\n </button>\r\n <button\r\n onClick={onFechar}\r\n className=\"text-micro font-black uppercase tracking-wider text-slate-500 hover:text-slate-700 px-2 py-1.5\"\r\n >\r\n {L.cancel}\r\n </button>\r\n {temFiltro && (\r\n <button\r\n onClick={onLimpar}\r\n className=\"text-micro font-black uppercase tracking-wider text-red-400 hover:text-red-500 px-2 py-1.5\"\r\n >\r\n {L.clearFilter}\r\n </button>\r\n )}\r\n </div>\r\n </div>,\r\n document.body,\r\n )\r\n}\r\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ColumnFilter.js","sources":["../../../../../../src/v1/components/tables/Table/ColumnFilter.tsx"],"sourcesContent":["import React, { useEffect, useId, useMemo, useRef, useState } from 'react'\r\nimport { createPortal } from 'react-dom'\r\nimport { CheckIcon, ChevronDownIcon, ChevronUpIcon, ListIcon, SlidersIcon } from '../../../foundations/icons/icons'\r\nimport type { TableLabels } from './labels'\r\n\r\n/** Onde o popup abre e quanto pode crescer. */\r\nconst ALTURA = 420\r\nconst LARGURA = 320\r\n\r\n/**\r\n * O filtro de uma coluna: ordenar, procurar, escolher valores, aplicar.\r\n *\r\n * Vive fora do `Table` de propósito. Lá dentro era uma função declarada no\r\n * corpo do componente, logo uma função NOVA a cada render — e o React\r\n * desmontava e remontava o popup a cada tecla escrita e a cada opção marcada.\r\n * Era isso que devolvia a lista de valores ao topo a meio de uma escolha.\r\n *\r\n * Nada se aplica até ao \"Aplicar\". Com a aplicação imediata, cada visto refazia\r\n * a tabela por baixo: mudava-lhe o tamanho e o conteúdo enquanto se escolhia, e\r\n * a lista de onde se estava a escolher encolhia à medida que se escolhia.\r\n *\r\n * `position: fixed` no `<body>`: como filho da célula, o `overflow` da tabela\r\n * cortava-o — e era por isso que a caixa da tabela tinha de perder o tecto de\r\n * altura enquanto um filtro estivesse aberto, o que empurrava a página inteira.\r\n */\r\nexport function ColumnFilter({\r\n labels: L, label, canSort, tipo, valores, seleccionados, intervalo, numero, ordenadaPor, aCarregar, ancora,\r\n onOrdenar, onAplicar, onAplicarDatas, onAplicarNumeros, onLimpar, onFechar,\r\n}: {\r\n labels: TableLabels\r\n label?: string\r\n canSort?: boolean\r\n /** `texto` = lista de valores; `data` = De/Até; `numero` = Mín/Máx, ou a lista (botão no topo). */\r\n tipo: 'texto' | 'data' | 'numero'\r\n /** Valores distintos da coluna, já contados com os outros filtros activos. */\r\n valores: string[]\r\n /** O que está aplicado neste momento — o ponto de partida do rascunho. */\r\n seleccionados: Set<string>\r\n intervalo: { from?: string; to?: string }\r\n /** Intervalo numérico aplicado, quando `tipo` é `numero`. */\r\n numero?: { min?: string; max?: string }\r\n ordenadaPor: 'asc' | 'desc' | null\r\n aCarregar: boolean\r\n /** Rect do botão que abriu isto. */\r\n ancora: DOMRect\r\n onOrdenar?: (dir: 'asc' | 'desc') => void\r\n onAplicar: (vals: Set<string>) => void\r\n onAplicarDatas?: (de: string, ate: string) => void\r\n onAplicarNumeros?: (min: string, max: string) => void\r\n onLimpar: () => void\r\n onFechar: () => void\r\n}) {\r\n const caixa = useRef<HTMLDivElement>(null)\r\n const idMin = useId()\r\n const [busca, setBusca] = useState('')\r\n /** O que está escolhido AGORA, sem ter saído daqui. Só o \"Aplicar\" o leva lá fora. */\r\n const [rascunho, setRascunho] = useState<Set<string>>(() => new Set(seleccionados))\r\n const [de, setDe] = useState(intervalo.from ?? '')\r\n const [ate, setAte] = useState(intervalo.to ?? '')\r\n const [min, setMin] = useState(numero?.min ?? '')\r\n const [max, setMax] = useState(numero?.max ?? '')\r\n /* Numa coluna de números, Mín/Máx ou a lista de valores. Abre na lista, salvo\r\n se já houver Mín/Máx aplicado: quem filtrou por intervalo e volta a abrir\r\n quer ver o intervalo. */\r\n const [modoLista, setModoLista] = useState(tipo === 'numero' && !numero?.min && !numero?.max)\r\n const lista = tipo === 'texto' || (tipo === 'numero' && modoLista)\r\n\r\n const visiveis = useMemo(() => {\r\n const achados = valores.filter(v => v.toLowerCase().includes(busca.toLowerCase()))\r\n // Por valor e não por texto: \"10\" antes de \"2\" numa lista de números é ruído.\r\n if (tipo !== 'numero') return achados\r\n return [...achados].sort((a, b) => {\r\n const na = Number(a), nb = Number(b)\r\n const va = a !== '—' && Number.isFinite(na), vb = b !== '—' && Number.isFinite(nb)\r\n if (va && vb) return na - nb\r\n return va ? -1 : vb ? 1 : a.localeCompare(b)\r\n })\r\n }, [valores, busca, tipo])\r\n const todosVisiveis = visiveis.length > 0 && visiveis.every(v => rascunho.has(v))\r\n const algunsVisiveis = visiveis.some(v => rascunho.has(v)) && !todosVisiveis\r\n\r\n /**\r\n * Marca ou desmarca os valores À VISTA — os que a pesquisa deixou passar.\r\n *\r\n * Com pesquisa activa, \"tudo\" é o que está no ecrã: escolher de uma vez os\r\n * valores que começam por \"Norte\" é o gesto que isto serve, e mexer nos\r\n * outros quarenta por baixo era o contrário do que se pediu.\r\n */\r\n const alternarTodos = () => setRascunho(prev => {\r\n const n = new Set(prev)\r\n if (todosVisiveis) for (const v of visiveis) n.delete(v)\r\n else for (const v of visiveis) n.add(v)\r\n return n\r\n })\r\n\r\n const alternar = (v: string) => setRascunho(prev => {\r\n const n = new Set(prev)\r\n if (n.has(v)) n.delete(v)\r\n else n.add(v)\r\n return n\r\n })\r\n\r\n const mesmoConjunto = (a: Set<string>, b: Set<string>) =>\r\n a.size === b.size && [...a].every(v => b.has(v))\r\n const sujo = tipo === 'data'\r\n ? de !== (intervalo.from ?? '') || ate !== (intervalo.to ?? '')\r\n : tipo === 'numero' && !modoLista\r\n ? min !== (numero?.min ?? '') || max !== (numero?.max ?? '')\r\n : !mesmoConjunto(rascunho, seleccionados)\r\n const temFiltro = seleccionados.size > 0 || !!intervalo.from || !!intervalo.to || !!numero?.min || !!numero?.max\r\n\r\n useEffect(() => {\r\n const fora = (e: MouseEvent) => {\r\n if (caixa.current && !caixa.current.contains(e.target as Node)) onFechar()\r\n }\r\n const tecla = (e: KeyboardEvent) => { if (e.key === 'Escape') onFechar() }\r\n /*\r\n Rolar FORA fecha; rolar DENTRO da lista não.\r\n A caixa está presa a coordenadas do ecrã, logo tem de fechar quando a\r\n página se move por baixo dela — mas a própria lista rola (podem ser\r\n dezenas de valores), e o `capture` também apanha esse.\r\n */\r\n const aoRolar = (e: Event) => {\r\n if (caixa.current && e.target instanceof Node && caixa.current.contains(e.target)) return\r\n onFechar()\r\n }\r\n document.addEventListener('mousedown', fora)\r\n document.addEventListener('keydown', tecla)\r\n window.addEventListener('scroll', aoRolar, true)\r\n window.addEventListener('resize', onFechar)\r\n return () => {\r\n document.removeEventListener('mousedown', fora)\r\n document.removeEventListener('keydown', tecla)\r\n window.removeEventListener('scroll', aoRolar, true)\r\n window.removeEventListener('resize', onFechar)\r\n }\r\n }, [onFechar])\r\n\r\n /* Troca Mín/Máx ↔ lista. Vai na linha que já existe (a do \"Mínimo\", ou a da\r\n pesquisa) e não numa só para ele: uma linha inteira para um botão pequeno\r\n era espaço vazio à esquerda. */\r\n const botaoModo = tipo === 'numero' && (\r\n <button\r\n type=\"button\"\r\n onClick={e => { e.preventDefault(); setModoLista(m => !m) }}\r\n title={modoLista ? L.showRange : L.showList}\r\n className=\"inline-flex items-center gap-1 text-[9px] font-black uppercase tracking-widest text-slate-400 hover:text-proef-blue flex-shrink-0 whitespace-nowrap\"\r\n >\r\n {modoLista ? <SlidersIcon size={10} /> : <ListIcon size={10} />}\r\n {modoLista ? L.showRange : L.showList}\r\n </button>\r\n )\r\n\r\n // Abre para cima quando não há espaço por baixo — nas colunas da direita e\r\n // com a janela baixa, o que ficava de fora eram os botões de aplicar.\r\n const paraCima = window.innerHeight - ancora.bottom < ALTURA && ancora.top > ALTURA\r\n\r\n return createPortal(\r\n <div\r\n ref={caixa}\r\n style={{\r\n position: 'fixed',\r\n left: Math.max(4, Math.min(ancora.left, window.innerWidth - LARGURA - 4)),\r\n ...(paraCima ? { bottom: window.innerHeight - ancora.top + 2 } : { top: ancora.bottom + 2 }),\r\n width: LARGURA,\r\n maxHeight: ALTURA,\r\n }}\r\n className=\"v1-reset z-[250] flex flex-col overflow-hidden rounded-lg bg-white border border-slate-200 shadow-lg\"\r\n >\r\n {label && (\r\n <div className=\"px-3 pt-2.5 pb-2 border-b border-slate-100 flex-shrink-0\">\r\n <span className=\"text-[9px] font-black uppercase tracking-widest text-proef-blue\">{label}</span>\r\n </div>\r\n )}\r\n {aCarregar && (\r\n <div className=\"px-3 py-1.5 bg-amber-50 border-b border-amber-100 flex items-center gap-1.5 text-micro text-amber-700 flex-shrink-0\">\r\n <span aria-hidden className=\"inline-block h-2.5 w-2.5 animate-spin rounded-full border-2 border-current border-t-transparent \" />\r\n {L.loadingOptions}\r\n </div>\r\n )}\r\n {canSort && onOrdenar && (\r\n <div className=\"border-b border-slate-100 p-1.5 space-y-0.5 flex-shrink-0\">\r\n <button\r\n onClick={() => onOrdenar('asc')}\r\n className={`w-full flex items-center gap-2 rounded-md px-2.5 py-1.5 text-caption font-semibold text-left hover:bg-slate-50 transition-colors ${ordenadaPor === 'asc' ? 'text-proef-blue bg-slate-50' : 'text-slate-600'}`}\r\n >\r\n <ChevronUpIcon size={11} /> {tipo === 'data' ? L.sortDateAsc : tipo === 'numero' ? L.sortNumAsc : L.sortAsc}\r\n </button>\r\n <button\r\n onClick={() => onOrdenar('desc')}\r\n className={`w-full flex items-center gap-2 rounded-md px-2.5 py-1.5 text-caption font-semibold text-left hover:bg-slate-50 transition-colors ${ordenadaPor === 'desc' ? 'text-proef-blue bg-slate-50' : 'text-slate-600'}`}\r\n >\r\n <ChevronDownIcon size={11} /> {tipo === 'data' ? L.sortDateDesc : tipo === 'numero' ? L.sortNumDesc : L.sortDesc}\r\n </button>\r\n </div>\r\n )}\r\n\r\n {tipo === 'data' ? (\r\n <div className=\"p-3 space-y-2\">\r\n <label className=\"block\">\r\n <span className=\"text-[9px] font-black uppercase tracking-widest text-slate-400\">{L.dateFrom}</span>\r\n <input\r\n type=\"date\" value={de} onChange={e => setDe(e.target.value)}\r\n onKeyDown={e => { if (e.key === 'Enter') onAplicarDatas?.(de, ate) }}\r\n className=\"w-full mt-0.5 rounded-md bg-slate-50 border border-slate-100 px-2.5 py-1.5 text-xs outline-none focus:border-proef-blue\"\r\n />\r\n </label>\r\n <label className=\"block\">\r\n <span className=\"text-[9px] font-black uppercase tracking-widest text-slate-400\">{L.dateTo}</span>\r\n <input\r\n type=\"date\" value={ate} onChange={e => setAte(e.target.value)}\r\n onKeyDown={e => { if (e.key === 'Enter') onAplicarDatas?.(de, ate) }}\r\n className=\"w-full mt-0.5 rounded-md bg-slate-50 border border-slate-100 px-2.5 py-1.5 text-xs outline-none focus:border-proef-blue\"\r\n />\r\n </label>\r\n </div>\r\n ) : !lista ? (\r\n /* Mín/Máx em vez da lista: numa coluna de dinheiro ou de contagem há\r\n tantos valores distintos quantas as linhas, e ninguém procura \"10.04\".\r\n Vazio de um dos lados vale \"sem limite desse lado\". */\r\n <div className=\"p-3 space-y-2\">\r\n {/* O botão da lista fica FORA da etiqueta: dentro dela, era o botão\r\n (e não a caixa) que recebia o nome \"Mínimo\", e a caixa ficava sem\r\n nome nenhum para os leitores de ecrã. */}\r\n <div>\r\n <span className=\"flex items-center justify-between\">\r\n <label htmlFor={idMin} className=\"text-[9px] font-black uppercase tracking-widest text-slate-400\">{L.min}</label>\r\n {botaoModo}\r\n </span>\r\n <input\r\n id={idMin}\r\n type=\"number\" value={min} onChange={e => setMin(e.target.value)}\r\n onKeyDown={e => { if (e.key === 'Enter') onAplicarNumeros?.(min, max) }}\r\n className=\"w-full mt-0.5 rounded-md bg-slate-50 border border-slate-100 px-2.5 py-1.5 text-xs outline-none focus:border-proef-blue\"\r\n />\r\n </div>\r\n <label className=\"block\">\r\n <span className=\"text-[9px] font-black uppercase tracking-widest text-slate-400\">{L.max}</span>\r\n <input\r\n type=\"number\" value={max} onChange={e => setMax(e.target.value)}\r\n onKeyDown={e => { if (e.key === 'Enter') onAplicarNumeros?.(min, max) }}\r\n className=\"w-full mt-0.5 rounded-md bg-slate-50 border border-slate-100 px-2.5 py-1.5 text-xs outline-none focus:border-proef-blue\"\r\n />\r\n </label>\r\n </div>\r\n ) : (\r\n <>\r\n <div className=\"p-1.5 flex-shrink-0 flex items-center gap-2\">\r\n <input\r\n autoFocus type=\"text\" value={busca} onChange={e => setBusca(e.target.value)} placeholder={L.search}\r\n className=\"flex-1 min-w-0 rounded-md bg-slate-50 border border-slate-100 px-2.5 py-1.5 text-xs outline-none focus:border-proef-blue\"\r\n />\r\n {botaoModo && <span className=\"pr-1.5\">{botaoModo}</span>}\r\n </div>\r\n {/* \"Tudo\" à cabeça da lista, como no Excel: marcar tudo e tirar o que\r\n não se quer é mais rápido do que marcar quarenta à mão. */}\r\n {visiveis.length > 0 && (\r\n <button\r\n onClick={alternarTodos}\r\n className=\"flex items-center gap-2 px-3 py-1.5 border-y border-slate-100 hover:bg-slate-50 text-left flex-shrink-0\"\r\n >\r\n <div className={`w-3.5 h-3.5 flex items-center justify-center rounded-sm border flex-shrink-0 transition-colors ${\r\n todosVisiveis ? 'bg-primary border-primary'\r\n : algunsVisiveis ? 'bg-primary/30 border-primary'\r\n : 'border-slate-300'\r\n }`}>\r\n {todosVisiveis && <CheckIcon size={9} strokeWidth={3} className=\"text-white\" />}\r\n </div>\r\n <span className=\"text-caption font-semibold text-slate-600\">\r\n {busca ? L.selectAllFound(visiveis.length) : L.selectAll}\r\n </span>\r\n </button>\r\n )}\r\n <div className=\"flex-1 overflow-y-auto p-1.5 space-y-0.5 min-h-0\">\r\n {visiveis.length === 0\r\n ? <p className=\"text-caption text-slate-400 text-center py-3\">{L.noResults}</p>\r\n : visiveis.map(v => {\r\n const escolhido = rascunho.has(v)\r\n return (\r\n <button key={v} onClick={() => alternar(v)} className=\"w-full flex items-center gap-2 rounded-md px-2 py-1.5 hover:bg-slate-50 text-left\">\r\n <div className={`w-3.5 h-3.5 flex items-center justify-center rounded-sm border flex-shrink-0 transition-colors ${escolhido ? 'bg-primary border-primary' : 'border-slate-300'}`}>\r\n {escolhido && <CheckIcon size={9} strokeWidth={3} className=\"text-white\" />}\r\n </div>\r\n <span className=\"text-xs text-slate-700 whitespace-normal break-words leading-snug\">{v}</span>\r\n </button>\r\n )\r\n })}\r\n </div>\r\n </>\r\n )}\r\n\r\n {/* Aplicar/Cancelar fora da zona que rola, sempre à vista: são eles que\r\n dizem que ainda não aconteceu nada. */}\r\n <div className=\"flex items-center gap-1.5 p-1.5 border-t border-slate-100 flex-shrink-0 bg-white\">\r\n <button\r\n onClick={() => {\r\n if (tipo === 'data') onAplicarDatas?.(de, ate)\r\n else if (tipo === 'numero' && !modoLista) onAplicarNumeros?.(min, max)\r\n else onAplicar(rascunho)\r\n }}\r\n disabled={!sujo}\r\n className=\"flex-1 text-micro font-black uppercase tracking-wider text-white bg-primary hover:bg-primary/90 rounded-md py-1.5 disabled:opacity-30\"\r\n >\r\n {L.apply}\r\n </button>\r\n <button\r\n onClick={onFechar}\r\n className=\"text-micro font-black uppercase tracking-wider text-slate-500 hover:text-slate-700 rounded-md px-2 py-1.5\"\r\n >\r\n {L.cancel}\r\n </button>\r\n {temFiltro && (\r\n <button\r\n onClick={onLimpar}\r\n className=\"text-micro font-black uppercase tracking-wider text-red-400 hover:text-red-500 rounded-md px-2 py-1.5\"\r\n >\r\n {L.clearFilter}\r\n </button>\r\n )}\r\n </div>\r\n </div>,\r\n document.body,\r\n )\r\n}\r\n"],"names":[],"mappings":";;;;AAMA,MAAM,SAAS;AACf,MAAM,UAAU;AAkBT,SAAS,aAAa;AAAA,EAC3B,QAAQ;AAAA,EAAG;AAAA,EAAO;AAAA,EAAS;AAAA,EAAM;AAAA,EAAS;AAAA,EAAe;AAAA,EAAW;AAAA,EAAQ;AAAA,EAAa;AAAA,EAAW;AAAA,EACpG;AAAA,EAAW;AAAA,EAAW;AAAA,EAAgB;AAAA,EAAkB;AAAA,EAAU;AACpE,GAuBG;AACD,QAAM,QAAQ,OAAuB,IAAI;AACzC,QAAM,QAAQ,MAAA;AACd,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE;AAErC,QAAM,CAAC,UAAU,WAAW,IAAI,SAAsB,MAAM,IAAI,IAAI,aAAa,CAAC;AAClF,QAAM,CAAC,IAAI,KAAK,IAAI,SAAS,UAAU,QAAQ,EAAE;AACjD,QAAM,CAAC,KAAK,MAAM,IAAI,SAAS,UAAU,MAAM,EAAE;AACjD,QAAM,CAAC,KAAK,MAAM,IAAI,SAAS,QAAQ,OAAO,EAAE;AAChD,QAAM,CAAC,KAAK,MAAM,IAAI,SAAS,QAAQ,OAAO,EAAE;AAIhD,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,SAAS,YAAY,CAAC,QAAQ,OAAO,CAAC,QAAQ,GAAG;AAC5F,QAAM,QAAQ,SAAS,WAAY,SAAS,YAAY;AAExD,QAAM,WAAW,QAAQ,MAAM;AAC7B,UAAM,UAAU,QAAQ,OAAO,CAAA,MAAK,EAAE,YAAA,EAAc,SAAS,MAAM,YAAA,CAAa,CAAC;AAEjF,QAAI,SAAS,SAAU,QAAO;AAC9B,WAAO,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM;AACjC,YAAM,KAAK,OAAO,CAAC,GAAG,KAAK,OAAO,CAAC;AACnC,YAAM,KAAK,MAAM,OAAO,OAAO,SAAS,EAAE,GAAG,KAAK,MAAM,OAAO,OAAO,SAAS,EAAE;AACjF,UAAI,MAAM,GAAI,QAAO,KAAK;AAC1B,aAAO,KAAK,KAAK,KAAK,IAAI,EAAE,cAAc,CAAC;AAAA,IAC7C,CAAC;AAAA,EACH,GAAG,CAAC,SAAS,OAAO,IAAI,CAAC;AACzB,QAAM,gBAAgB,SAAS,SAAS,KAAK,SAAS,MAAM,CAAA,MAAK,SAAS,IAAI,CAAC,CAAC;AAChF,QAAM,iBAAiB,SAAS,KAAK,CAAA,MAAK,SAAS,IAAI,CAAC,CAAC,KAAK,CAAC;AAS/D,QAAM,gBAAgB,MAAM,YAAY,CAAA,SAAQ;AAC9C,UAAM,IAAI,IAAI,IAAI,IAAI;AACtB,QAAI,cAAe,YAAW,KAAK,SAAU,GAAE,OAAO,CAAC;AAAA,QAClD,YAAW,KAAK,SAAU,GAAE,IAAI,CAAC;AACtC,WAAO;AAAA,EACT,CAAC;AAED,QAAM,WAAW,CAAC,MAAc,YAAY,CAAA,SAAQ;AAClD,UAAM,IAAI,IAAI,IAAI,IAAI;AACtB,QAAI,EAAE,IAAI,CAAC,EAAG,GAAE,OAAO,CAAC;AAAA,QACnB,GAAE,IAAI,CAAC;AACZ,WAAO;AAAA,EACT,CAAC;AAED,QAAM,gBAAgB,CAAC,GAAgB,MACrC,EAAE,SAAS,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,OAAK,EAAE,IAAI,CAAC,CAAC;AACjD,QAAM,OAAO,SAAS,SAClB,QAAQ,UAAU,QAAQ,OAAO,SAAS,UAAU,MAAM,MAC1D,SAAS,YAAY,CAAC,YACpB,SAAS,QAAQ,OAAO,OAAO,SAAS,QAAQ,OAAO,MACvD,CAAC,cAAc,UAAU,aAAa;AAC5C,QAAM,YAAY,cAAc,OAAO,KAAK,CAAC,CAAC,UAAU,QAAQ,CAAC,CAAC,UAAU,MAAM,CAAC,CAAC,QAAQ,OAAO,CAAC,CAAC,QAAQ;AAE7G,YAAU,MAAM;AACd,UAAM,OAAO,CAAC,MAAkB;AAC9B,UAAI,MAAM,WAAW,CAAC,MAAM,QAAQ,SAAS,EAAE,MAAc,EAAG,UAAA;AAAA,IAClE;AACA,UAAM,QAAQ,CAAC,MAAqB;AAAE,UAAI,EAAE,QAAQ,SAAU,UAAA;AAAA,IAAW;AAOzE,UAAM,UAAU,CAAC,MAAa;AAC5B,UAAI,MAAM,WAAW,EAAE,kBAAkB,QAAQ,MAAM,QAAQ,SAAS,EAAE,MAAM,EAAG;AACnF,eAAA;AAAA,IACF;AACA,aAAS,iBAAiB,aAAa,IAAI;AAC3C,aAAS,iBAAiB,WAAW,KAAK;AAC1C,WAAO,iBAAiB,UAAU,SAAS,IAAI;AAC/C,WAAO,iBAAiB,UAAU,QAAQ;AAC1C,WAAO,MAAM;AACX,eAAS,oBAAoB,aAAa,IAAI;AAC9C,eAAS,oBAAoB,WAAW,KAAK;AAC7C,aAAO,oBAAoB,UAAU,SAAS,IAAI;AAClD,aAAO,oBAAoB,UAAU,QAAQ;AAAA,IAC/C;AAAA,EACF,GAAG,CAAC,QAAQ,CAAC;AAKb,QAAM,YAAY,SAAS,YACzB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,SAAS,CAAA,MAAK;AAAE,UAAE,eAAA;AAAkB,qBAAa,CAAA,MAAK,CAAC,CAAC;AAAA,MAAE;AAAA,MAC1D,OAAO,YAAY,EAAE,YAAY,EAAE;AAAA,MACnC,WAAU;AAAA,MAET,UAAA;AAAA,QAAA,YAAY,oBAAC,eAAY,MAAM,GAAA,CAAI,IAAK,oBAAC,UAAA,EAAS,MAAM,GAAA,CAAI;AAAA,QAC5D,YAAY,EAAE,YAAY,EAAE;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAMjC,QAAM,WAAW,OAAO,cAAc,OAAO,SAAS,UAAU,OAAO,MAAM;AAE7E,SAAO;AAAA,IACL;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAK;AAAA,QACL,OAAO;AAAA,UACL,UAAU;AAAA,UACV,MAAM,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,MAAM,OAAO,aAAa,UAAU,CAAC,CAAC;AAAA,UACxE,GAAI,WAAW,EAAE,QAAQ,OAAO,cAAc,OAAO,MAAM,EAAA,IAAM,EAAE,KAAK,OAAO,SAAS,EAAA;AAAA,UACxF,OAAO;AAAA,UACP,WAAW;AAAA,QAAA;AAAA,QAEb,WAAU;AAAA,QAET,UAAA;AAAA,UAAA,SACC,oBAAC,SAAI,WAAU,4DACb,8BAAC,QAAA,EAAK,WAAU,mEAAmE,UAAA,MAAA,CAAM,EAAA,CAC3F;AAAA,UAED,aACC,qBAAC,OAAA,EAAI,WAAU,uHACb,UAAA;AAAA,YAAA,oBAAC,QAAA,EAAK,eAAW,MAAC,WAAU,oGAAmG;AAAA,YAC9H,EAAE;AAAA,UAAA,GACL;AAAA,UAED,WAAW,aACV,qBAAC,OAAA,EAAI,WAAU,6DACb,UAAA;AAAA,YAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,SAAS,MAAM,UAAU,KAAK;AAAA,gBAC9B,WAAW,oIAAoI,gBAAgB,QAAQ,gCAAgC,gBAAgB;AAAA,gBAEvN,UAAA;AAAA,kBAAA,oBAAC,eAAA,EAAc,MAAM,GAAA,CAAI;AAAA,kBAAE;AAAA,kBAAE,SAAS,SAAS,EAAE,cAAc,SAAS,WAAW,EAAE,aAAa,EAAE;AAAA,gBAAA;AAAA,cAAA;AAAA,YAAA;AAAA,YAEtG;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,SAAS,MAAM,UAAU,MAAM;AAAA,gBAC/B,WAAW,oIAAoI,gBAAgB,SAAS,gCAAgC,gBAAgB;AAAA,gBAExN,UAAA;AAAA,kBAAA,oBAAC,iBAAA,EAAgB,MAAM,GAAA,CAAI;AAAA,kBAAE;AAAA,kBAAE,SAAS,SAAS,EAAE,eAAe,SAAS,WAAW,EAAE,cAAc,EAAE;AAAA,gBAAA;AAAA,cAAA;AAAA,YAAA;AAAA,UAC1G,GACF;AAAA,UAGD,SAAS,SACR,qBAAC,OAAA,EAAI,WAAU,iBACb,UAAA;AAAA,YAAA,qBAAC,SAAA,EAAM,WAAU,SACf,UAAA;AAAA,cAAA,oBAAC,QAAA,EAAK,WAAU,kEAAkE,UAAA,EAAE,UAAS;AAAA,cAC7F;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,MAAK;AAAA,kBAAO,OAAO;AAAA,kBAAI,UAAU,CAAA,MAAK,MAAM,EAAE,OAAO,KAAK;AAAA,kBAC1D,WAAW,CAAA,MAAK;AAAE,wBAAI,EAAE,QAAQ,QAAS,kBAAiB,IAAI,GAAG;AAAA,kBAAE;AAAA,kBACnE,WAAU;AAAA,gBAAA;AAAA,cAAA;AAAA,YACZ,GACF;AAAA,YACA,qBAAC,SAAA,EAAM,WAAU,SACf,UAAA;AAAA,cAAA,oBAAC,QAAA,EAAK,WAAU,kEAAkE,UAAA,EAAE,QAAO;AAAA,cAC3F;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,MAAK;AAAA,kBAAO,OAAO;AAAA,kBAAK,UAAU,CAAA,MAAK,OAAO,EAAE,OAAO,KAAK;AAAA,kBAC5D,WAAW,CAAA,MAAK;AAAE,wBAAI,EAAE,QAAQ,QAAS,kBAAiB,IAAI,GAAG;AAAA,kBAAE;AAAA,kBACnE,WAAU;AAAA,gBAAA;AAAA,cAAA;AAAA,YACZ,EAAA,CACF;AAAA,UAAA,EAAA,CACF,IACE,CAAC;AAAA;AAAA;AAAA;AAAA,YAIH,qBAAC,OAAA,EAAI,WAAU,iBAIb,UAAA;AAAA,cAAA,qBAAC,OAAA,EACC,UAAA;AAAA,gBAAA,qBAAC,QAAA,EAAK,WAAU,qCACd,UAAA;AAAA,kBAAA,oBAAC,WAAM,SAAS,OAAO,WAAU,kEAAkE,YAAE,KAAI;AAAA,kBACxG;AAAA,gBAAA,GACH;AAAA,gBACA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,IAAI;AAAA,oBACJ,MAAK;AAAA,oBAAS,OAAO;AAAA,oBAAK,UAAU,CAAA,MAAK,OAAO,EAAE,OAAO,KAAK;AAAA,oBAC9D,WAAW,CAAA,MAAK;AAAE,0BAAI,EAAE,QAAQ,QAAS,oBAAmB,KAAK,GAAG;AAAA,oBAAE;AAAA,oBACtE,WAAU;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACZ,GACF;AAAA,cACA,qBAAC,SAAA,EAAM,WAAU,SACf,UAAA;AAAA,gBAAA,oBAAC,QAAA,EAAK,WAAU,kEAAkE,UAAA,EAAE,KAAI;AAAA,gBACxF;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,MAAK;AAAA,oBAAS,OAAO;AAAA,oBAAK,UAAU,CAAA,MAAK,OAAO,EAAE,OAAO,KAAK;AAAA,oBAC9D,WAAW,CAAA,MAAK;AAAE,0BAAI,EAAE,QAAQ,QAAS,oBAAmB,KAAK,GAAG;AAAA,oBAAE;AAAA,oBACtE,WAAU;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACZ,EAAA,CACF;AAAA,YAAA,EAAA,CACF;AAAA,cAEA,qBAAA,UAAA,EACE,UAAA;AAAA,YAAA,qBAAC,OAAA,EAAI,WAAU,+CACb,UAAA;AAAA,cAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,WAAS;AAAA,kBAAC,MAAK;AAAA,kBAAO,OAAO;AAAA,kBAAO,UAAU,CAAA,MAAK,SAAS,EAAE,OAAO,KAAK;AAAA,kBAAG,aAAa,EAAE;AAAA,kBAC5F,WAAU;AAAA,gBAAA;AAAA,cAAA;AAAA,cAEX,aAAa,oBAAC,QAAA,EAAK,WAAU,UAAU,UAAA,UAAA,CAAU;AAAA,YAAA,GACpD;AAAA,YAGC,SAAS,SAAS,KACjB;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,SAAS;AAAA,gBACT,WAAU;AAAA,gBAEV,UAAA;AAAA,kBAAA,oBAAC,SAAI,WAAW,kGACd,gBAAgB,8BACZ,iBAAiB,iCACf,kBACR,IACG,UAAA,iBAAiB,oBAAC,aAAU,MAAM,GAAG,aAAa,GAAG,WAAU,cAAa,EAAA,CAC/E;AAAA,kBACA,oBAAC,QAAA,EAAK,WAAU,6CACb,UAAA,QAAQ,EAAE,eAAe,SAAS,MAAM,IAAI,EAAE,UAAA,CACjD;AAAA,gBAAA;AAAA,cAAA;AAAA,YAAA;AAAA,gCAGH,OAAA,EAAI,WAAU,oDACZ,UAAA,SAAS,WAAW,IACjB,oBAAC,KAAA,EAAE,WAAU,gDAAgD,UAAA,EAAE,UAAA,CAAU,IACzE,SAAS,IAAI,CAAA,MAAK;AAClB,oBAAM,YAAY,SAAS,IAAI,CAAC;AAChC,qBACE,qBAAC,YAAe,SAAS,MAAM,SAAS,CAAC,GAAG,WAAU,qFACpD,UAAA;AAAA,gBAAA,oBAAC,SAAI,WAAW,kGAAkG,YAAY,8BAA8B,kBAAkB,IAC3K,UAAA,aAAa,oBAAC,WAAA,EAAU,MAAM,GAAG,aAAa,GAAG,WAAU,cAAa,GAC3E;AAAA,gBACA,oBAAC,QAAA,EAAK,WAAU,qEAAqE,UAAA,EAAA,CAAE;AAAA,cAAA,EAAA,GAJ5E,CAKb;AAAA,YAEJ,CAAC,EAAA,CACL;AAAA,UAAA,GACF;AAAA,UAKF,qBAAC,OAAA,EAAI,WAAU,oFACb,UAAA;AAAA,YAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,SAAS,MAAM;AACb,sBAAI,SAAS,OAAQ,kBAAiB,IAAI,GAAG;AAAA,2BACpC,SAAS,YAAY,CAAC,UAAW,oBAAmB,KAAK,GAAG;AAAA,iCACtD,QAAQ;AAAA,gBACzB;AAAA,gBACA,UAAU,CAAC;AAAA,gBACX,WAAU;AAAA,gBAET,UAAA,EAAE;AAAA,cAAA;AAAA,YAAA;AAAA,YAEL;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,SAAS;AAAA,gBACT,WAAU;AAAA,gBAET,UAAA,EAAE;AAAA,cAAA;AAAA,YAAA;AAAA,YAEJ,aACC;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,SAAS;AAAA,gBACT,WAAU;AAAA,gBAET,UAAA,EAAE;AAAA,cAAA;AAAA,YAAA;AAAA,UACL,EAAA,CAEJ;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,IAEF,SAAS;AAAA,EAAA;AAEb;"}
|
|
@@ -52,6 +52,7 @@ function TableBase({
|
|
|
52
52
|
overlayScrollbars: barraSobreposta = false,
|
|
53
53
|
headerRowClassName: classeCabecalho = "bg-slate-50",
|
|
54
54
|
scrollbarOnEdge: barraNaBorda = true,
|
|
55
|
+
bordered: comCaixa = false,
|
|
55
56
|
horizontalScrollbarBelow: barraHorizontalFora = false,
|
|
56
57
|
skeleton: esqueletoAoCarregar = false,
|
|
57
58
|
fadeRight: esbaterDireita = false,
|
|
@@ -652,7 +653,7 @@ function TableBase({
|
|
|
652
653
|
selectable && /* @__PURE__ */ jsx("td", { style: fixa(0, fundoLinha(rowKey(row))).style, className: `px-4 py-3 ${fixa(0, fundoLinha(rowKey(row))).className}`, onClick: (e) => {
|
|
653
654
|
e.stopPropagation();
|
|
654
655
|
toggleRow(rowKey(row));
|
|
655
|
-
}, children: /* @__PURE__ */ jsx("div", { className: `w-4 h-4 flex items-center justify-center border transition-colors ${selectedKeys.has(rowKey(row)) ? "bg-primary border-primary" : "border-slate-300 hover:border-slate-400"}`, children: selectedKeys.has(rowKey(row)) && /* @__PURE__ */ jsx(CheckIcon, { size: 9, strokeWidth: 3, className: "text-white" }) }) }),
|
|
656
|
+
}, children: /* @__PURE__ */ jsx("div", { className: `w-4 h-4 flex items-center justify-center rounded-sm border transition-colors ${selectedKeys.has(rowKey(row)) ? "bg-primary border-primary" : "border-slate-300 hover:border-slate-400"}`, children: selectedKeys.has(rowKey(row)) && /* @__PURE__ */ jsx(CheckIcon, { size: 9, strokeWidth: 3, className: "text-white" }) }) }),
|
|
656
657
|
columns.map((col, i) => {
|
|
657
658
|
const f = fixa(i + (selectable ? 1 : 0), fundoLinha(rowKey(row)));
|
|
658
659
|
return /* @__PURE__ */ jsx("td", { style: f.style, className: `px-3 py-1.5 ${col.cellClassName ?? ""} ${f.className} ${recuoFim(i)} ${realce(col.key)} ${transicaoRealce}`, "data-col": col.key, children: col.render(row) }, col.key);
|
|
@@ -888,7 +889,7 @@ function TableBase({
|
|
|
888
889
|
const grupoColunas = largurasVista ? /* @__PURE__ */ jsx("colgroup", { children: chavesVista.map((k) => /* @__PURE__ */ jsx("col", { style: { width: largurasVista[k] } }, k)) }) : null;
|
|
889
890
|
const estiloTabela = largurasVista ? { tableLayout: "fixed", width: chavesVista.reduce((a, k) => a + (largurasVista[k] ?? 0), 0), minWidth: "100%" } : { width: "max-content" };
|
|
890
891
|
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: [
|
|
891
|
-
selectable && /* @__PURE__ */ jsx("th", { style: cabecaFixa(0).style, className: `px-4 py-3 w-10 ${fundoNosTitulos ? "bg-slate-50" : ""} ${cabecaFixa(0).className}`, children: /* @__PURE__ */ jsx("button", { onClick: toggleAll, className: `w-4 h-4 flex items-center justify-center border transition-colors ${allVisibleSelected ? "bg-primary border-primary" : someVisibleSelected ? "bg-slate-300 border-slate-300" : "border-slate-300 hover:border-slate-400"}`, children: (allVisibleSelected || someVisibleSelected) && /* @__PURE__ */ jsx(CheckIcon, { size: 9, strokeWidth: 3, className: "text-white" }) }) }),
|
|
892
|
+
selectable && /* @__PURE__ */ jsx("th", { style: cabecaFixa(0).style, className: `px-4 py-3 w-10 ${fundoNosTitulos ? "bg-slate-50" : ""} ${cabecaFixa(0).className}`, children: /* @__PURE__ */ jsx("button", { onClick: toggleAll, className: `w-4 h-4 flex items-center justify-center rounded-sm border transition-colors ${allVisibleSelected ? "bg-primary border-primary" : someVisibleSelected ? "bg-slate-300 border-slate-300" : "border-slate-300 hover:border-slate-400"}`, children: (allVisibleSelected || someVisibleSelected) && /* @__PURE__ */ jsx(CheckIcon, { size: 9, strokeWidth: 3, className: "text-white" }) }) }),
|
|
892
893
|
columns.map((col, i) => {
|
|
893
894
|
const canSort = col.sortable !== false && !!col.value;
|
|
894
895
|
const canFilter = col.filterable !== false && !!col.value;
|
|
@@ -1063,7 +1064,7 @@ function TableBase({
|
|
|
1063
1064
|
] }) });
|
|
1064
1065
|
const LARGURAS_ESQUELETO = ["w-3/4", "w-1/2", "w-2/3", "w-5/6", "w-2/5"];
|
|
1065
1066
|
const linhasEsqueleto = Array.from({ length: 20 }, (_, r) => /* @__PURE__ */ jsxs("tr", { "aria-hidden": true, className: "animate-pulse motion-reduce:animate-none", children: [
|
|
1066
|
-
selectable && /* @__PURE__ */ jsx("td", { style: fixa(0, "bg-white").style, className: `px-4 py-3 ${fixa(0, "bg-white").className}`, children: /* @__PURE__ */ jsx("div", { className: "w-4 h-4 border border-slate-200 bg-slate-50" }) }),
|
|
1067
|
+
selectable && /* @__PURE__ */ jsx("td", { style: fixa(0, "bg-white").style, className: `px-4 py-3 ${fixa(0, "bg-white").className}`, children: /* @__PURE__ */ jsx("div", { className: "w-4 h-4 rounded-sm border border-slate-200 bg-slate-50" }) }),
|
|
1067
1068
|
columns.map((col, i) => {
|
|
1068
1069
|
const f = fixa(i + (selectable ? 1 : 0), "bg-white");
|
|
1069
1070
|
return /* @__PURE__ */ jsx("td", { style: f.style, className: `px-3 py-2.5 ${f.className} ${recuoFim(i)}`, children: /* @__PURE__ */ jsx("div", { className: `h-2 bg-slate-200 ${LARGURAS_ESQUELETO[(r + i) % LARGURAS_ESQUELETO.length]} ${/text-right/.test(col.cellClassName ?? "") ? "ml-auto" : /text-center/.test(col.cellClassName ?? "") ? "mx-auto" : ""}` }) }, col.key);
|
|
@@ -1079,7 +1080,7 @@ function TableBase({
|
|
|
1079
1080
|
selectable && /* @__PURE__ */ jsx("td", { style: fixa(0, fundoLinha(rowKey(row))).style, className: `px-4 py-3 ${fixa(0, fundoLinha(rowKey(row))).className}`, onClick: (e) => {
|
|
1080
1081
|
e.stopPropagation();
|
|
1081
1082
|
toggleRow(rowKey(row));
|
|
1082
|
-
}, children: /* @__PURE__ */ jsx("div", { className: `w-4 h-4 flex items-center justify-center border transition-colors ${selectedKeys.has(rowKey(row)) ? "bg-primary border-primary" : "border-slate-300 hover:border-slate-400"}`, children: selectedKeys.has(rowKey(row)) && /* @__PURE__ */ jsx(CheckIcon, { size: 9, strokeWidth: 3, className: "text-white" }) }) }),
|
|
1083
|
+
}, children: /* @__PURE__ */ jsx("div", { className: `w-4 h-4 flex items-center justify-center rounded-sm border transition-colors ${selectedKeys.has(rowKey(row)) ? "bg-primary border-primary" : "border-slate-300 hover:border-slate-400"}`, children: selectedKeys.has(rowKey(row)) && /* @__PURE__ */ jsx(CheckIcon, { size: 9, strokeWidth: 3, className: "text-white" }) }) }),
|
|
1083
1084
|
columns.map((col, i) => {
|
|
1084
1085
|
const f = fixa(i + (selectable ? 1 : 0), fundoLinha(rowKey(row)));
|
|
1085
1086
|
return /* @__PURE__ */ jsx("td", { style: f.style, className: `px-3 py-1.5 ${col.cellClassName ?? ""} ${f.className} ${recuoFim(i)} ${realce(col.key)} ${transicaoRealce}`, "data-col": col.key, children: col.render(row) }, col.key);
|
|
@@ -1295,7 +1296,7 @@ function TableBase({
|
|
|
1295
1296
|
/* A coluna só existe a preencher: as barras de chips e o rodapé são irmãos
|
|
1296
1297
|
da caixa de scroll, e é a coluna que lhes dá topo e fundo fixos com o
|
|
1297
1298
|
scroll pelo meio. */
|
|
1298
|
-
/* @__PURE__ */ jsxs("div", { ref: raizRef, className: `v1-reset text-control text-slate-800 ${preencheAltura ? "h-full min-h-0 flex flex-col" : ""}`, children: [
|
|
1299
|
+
/* @__PURE__ */ jsxs("div", { ref: raizRef, className: `v1-reset text-control text-slate-800 ${preencheAltura ? "h-full min-h-0 flex flex-col" : ""} ${comCaixa ? "rounded-xl border border-slate-200 bg-white overflow-hidden" : ""}`, children: [
|
|
1299
1300
|
barraTopo,
|
|
1300
1301
|
!topo && isGrouped && /* @__PURE__ */ jsx("div", { className: "px-4 py-2 bg-slate-50 border-b border-slate-200 flex items-center gap-1.5 flex-wrap", children: chipsGrupo }),
|
|
1301
1302
|
!topo && totalActiveFilters > 0 && /* @__PURE__ */ jsx("div", { className: "px-4 py-2 bg-slate-50 border-b border-slate-200 flex items-center gap-1.5 flex-wrap", children: chipsFiltro }),
|
|
@@ -1337,7 +1338,7 @@ function TableBase({
|
|
|
1337
1338
|
}
|
|
1338
1339
|
),
|
|
1339
1340
|
barraSobreposta && /* @__PURE__ */ jsx(OverlayScrollbar, { alvo: caixaCorpo, borda: 0, canto: !barraHorizontalFora }),
|
|
1340
|
-
barraSobreposta && /* @__PURE__ */ jsx(OverlayScrollbar, { alvo: caixaCorpo, eixo: "horizontal", borda: 0, canto: !barraHorizontalFora, naBorda: !barraHorizontalFora && barraNaBorda && temRodape })
|
|
1341
|
+
barraSobreposta && /* @__PURE__ */ jsx(OverlayScrollbar, { alvo: caixaCorpo, eixo: "horizontal", borda: 0, canto: !barraHorizontalFora, naBorda: !barraHorizontalFora && barraNaBorda && !comCaixa && temRodape })
|
|
1341
1342
|
] }),
|
|
1342
1343
|
exemplares && /* @__PURE__ */ jsx(
|
|
1343
1344
|
"table",
|
|
@@ -1376,7 +1377,7 @@ function TableBase({
|
|
|
1376
1377
|
{
|
|
1377
1378
|
disabled: internalPage <= 1,
|
|
1378
1379
|
onClick: () => setInternalPage((p) => p - 1),
|
|
1379
|
-
className: "flex items-center gap-1 px-3 py-1.5 text-micro font-black uppercase tracking-widest bg-white border border-slate-200 disabled:opacity-30 hover:enabled:border-proef-blue hover:enabled:text-proef-blue transition-colors",
|
|
1380
|
+
className: "flex items-center gap-1 px-3 py-1.5 rounded-md text-micro font-black uppercase tracking-widest bg-white border border-slate-200 disabled:opacity-30 hover:enabled:border-proef-blue hover:enabled:text-proef-blue transition-colors",
|
|
1380
1381
|
children: [
|
|
1381
1382
|
/* @__PURE__ */ jsx(ChevronLeftIcon, { size: 12 }),
|
|
1382
1383
|
L.prev
|
|
@@ -1388,7 +1389,7 @@ function TableBase({
|
|
|
1388
1389
|
{
|
|
1389
1390
|
disabled: internalPage >= internalTotalPages,
|
|
1390
1391
|
onClick: () => setInternalPage((p) => p + 1),
|
|
1391
|
-
className: "flex items-center gap-1 px-3 py-1.5 text-micro font-black uppercase tracking-widest bg-white border border-slate-200 disabled:opacity-30 hover:enabled:border-proef-blue hover:enabled:text-proef-blue transition-colors",
|
|
1392
|
+
className: "flex items-center gap-1 px-3 py-1.5 rounded-md text-micro font-black uppercase tracking-widest bg-white border border-slate-200 disabled:opacity-30 hover:enabled:border-proef-blue hover:enabled:text-proef-blue transition-colors",
|
|
1392
1393
|
children: [
|
|
1393
1394
|
L.next,
|
|
1394
1395
|
/* @__PURE__ */ jsx(ChevronRightIcon, { size: 12 })
|