@nextelco/common-ui 2.1.105 → 2.1.107

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.
Files changed (199) hide show
  1. package/dist/esm/index.js +201 -145
  2. package/dist/esm/index.js.map +1 -1
  3. package/dist/esm/legacy/components/atoms/InputData/InputData.js +2 -13
  4. package/dist/esm/legacy/components/atoms/InputData/InputData.js.map +1 -1
  5. package/dist/esm/legacy/components/charts/Charts.js +147 -57
  6. package/dist/esm/legacy/components/charts/Charts.js.map +1 -1
  7. package/dist/esm/legacy/components/layout/Layout/Layout.js +21 -82
  8. package/dist/esm/legacy/components/layout/Layout/Layout.js.map +1 -1
  9. package/dist/esm/legacy/components/layout/Sidebar/Sidebar.js +29 -218
  10. package/dist/esm/legacy/components/layout/Sidebar/Sidebar.js.map +1 -1
  11. package/dist/esm/legacy/components/molecules/ColumnPicker/ColumnPicker.js +77 -10
  12. package/dist/esm/legacy/components/molecules/ColumnPicker/ColumnPicker.js.map +1 -1
  13. package/dist/esm/legacy/components/molecules/DataTable/DataTable.js +445 -337
  14. package/dist/esm/legacy/components/molecules/DataTable/DataTable.js.map +1 -1
  15. package/dist/esm/legacy/components/molecules/UserAvatar/UserAvatar.js +15 -97
  16. package/dist/esm/legacy/components/molecules/UserAvatar/UserAvatar.js.map +1 -1
  17. package/dist/esm/legacy/components/organisms/MapaPontos/MapaPontos.js +3 -3
  18. package/dist/esm/legacy/components/organisms/MapaPontos/MapaPontos.js.map +1 -1
  19. package/dist/esm/legacy/components/organisms/PainelFiltros/PainelFiltros.js +15 -3
  20. package/dist/esm/legacy/components/organisms/PainelFiltros/PainelFiltros.js.map +1 -1
  21. package/dist/esm/legacy/components/organisms/Selector/Selector.js +4 -4
  22. package/dist/esm/legacy/components/organisms/Selector/Selector.js.map +1 -1
  23. package/dist/esm/legacy/components/ui/Avisos.js +23 -76
  24. package/dist/esm/legacy/components/ui/Avisos.js.map +1 -1
  25. package/dist/esm/legacy/components/ui/CabecalhoPagina.js +14 -27
  26. package/dist/esm/legacy/components/ui/CabecalhoPagina.js.map +1 -1
  27. package/dist/esm/legacy/components/ui/CaixaPesquisa.js +3 -51
  28. package/dist/esm/legacy/components/ui/CaixaPesquisa.js.map +1 -1
  29. package/dist/esm/legacy/components/ui/Confirmacao.js +13 -31
  30. package/dist/esm/legacy/components/ui/Confirmacao.js.map +1 -1
  31. package/dist/esm/legacy/components/ui/Escolha.js +21 -137
  32. package/dist/esm/legacy/components/ui/Escolha.js.map +1 -1
  33. package/dist/esm/legacy/components/ui/FaixaAviso.js +13 -11
  34. package/dist/esm/legacy/components/ui/FaixaAviso.js.map +1 -1
  35. package/dist/esm/legacy/components/ui/Separadores.js +11 -46
  36. package/dist/esm/legacy/components/ui/Separadores.js.map +1 -1
  37. package/dist/esm/legacy/components/ui/Ui.js +18 -115
  38. package/dist/esm/legacy/components/ui/Ui.js.map +1 -1
  39. package/dist/esm/legacy/components/ui/painelFlutuante.js +5 -44
  40. package/dist/esm/legacy/components/ui/painelFlutuante.js.map +1 -1
  41. package/dist/esm/v1/capabilities/overlay/useFloatingPanel.js +52 -0
  42. package/dist/esm/v1/capabilities/overlay/useFloatingPanel.js.map +1 -0
  43. package/dist/esm/v1/capabilities/theme/useIsDark.js +15 -0
  44. package/dist/esm/v1/capabilities/theme/useIsDark.js.map +1 -0
  45. package/dist/esm/v1/capabilities/theme/useTheme.js +66 -0
  46. package/dist/esm/v1/capabilities/theme/useTheme.js.map +1 -0
  47. package/dist/esm/v1/components/data/Pagination/Pagination.js +66 -0
  48. package/dist/esm/v1/components/data/Pagination/Pagination.js.map +1 -0
  49. package/dist/esm/v1/components/feedback/Toast/Toast.js +105 -0
  50. package/dist/esm/v1/components/feedback/Toast/Toast.js.map +1 -0
  51. package/dist/esm/v1/components/forms/FormField/FormField.js.map +1 -1
  52. package/dist/esm/v1/components/forms/FormGrid/FormGrid.js.map +1 -1
  53. package/dist/esm/v1/components/layout/AppShell/AppShell.js +89 -0
  54. package/dist/esm/v1/components/layout/AppShell/AppShell.js.map +1 -0
  55. package/dist/esm/v1/components/layout/Page/Page.js +16 -0
  56. package/dist/esm/v1/components/layout/Page/Page.js.map +1 -0
  57. package/dist/esm/v1/components/layout/PageHeader/PageHeader.js +26 -0
  58. package/dist/esm/v1/components/layout/PageHeader/PageHeader.js.map +1 -0
  59. package/dist/esm/v1/components/layout/SideNav/SideNav.js +277 -0
  60. package/dist/esm/v1/components/layout/SideNav/SideNav.js.map +1 -0
  61. package/dist/esm/v1/components/layout/navTrail.js +19 -0
  62. package/dist/esm/v1/components/layout/navTrail.js.map +1 -0
  63. package/dist/esm/v1/components/lists/ListFinder/ListFinder.js +4 -4
  64. package/dist/esm/v1/components/lists/ListFinder/ListFinder.js.map +1 -1
  65. package/dist/esm/v1/components/overlays/ConfirmDialog/ConfirmDialog.js +95 -0
  66. package/dist/esm/v1/components/overlays/ConfirmDialog/ConfirmDialog.js.map +1 -0
  67. package/dist/esm/v1/components/overlays/Dialog/Dialog.js.map +1 -1
  68. package/dist/esm/v1/components/overlays/Tooltip/Tooltip.js +98 -0
  69. package/dist/esm/v1/components/overlays/Tooltip/Tooltip.js.map +1 -0
  70. package/dist/esm/v1/components/overlays/Tooltip/TooltipLayer.js +84 -0
  71. package/dist/esm/v1/components/overlays/Tooltip/TooltipLayer.js.map +1 -0
  72. package/dist/esm/v1/components/overlays/Tooltip/TooltipPanel.js +33 -0
  73. package/dist/esm/v1/components/overlays/Tooltip/TooltipPanel.js.map +1 -0
  74. package/dist/esm/v1/components/overlays/topLayer.js +28 -0
  75. package/dist/esm/v1/components/overlays/topLayer.js.map +1 -0
  76. package/dist/esm/v1/components/tables/PaginatedTable/PaginatedTable.js.map +1 -1
  77. package/dist/esm/v1/components/tables/Table/Table.js.map +1 -1
  78. package/dist/esm/v1/foundations/icons/icons.js +61 -2
  79. package/dist/esm/v1/foundations/icons/icons.js.map +1 -1
  80. package/dist/esm/v1/primitives/buttons/Button/Button.js +18 -4
  81. package/dist/esm/v1/primitives/buttons/Button/Button.js.map +1 -1
  82. package/dist/esm/v1/primitives/buttons/SegmentedControl/SegmentedControl.js +65 -0
  83. package/dist/esm/v1/primitives/buttons/SegmentedControl/SegmentedControl.js.map +1 -0
  84. package/dist/esm/v1/primitives/buttons/SegmentedControl/segmentedStyles.js +10 -0
  85. package/dist/esm/v1/primitives/buttons/SegmentedControl/segmentedStyles.js.map +1 -0
  86. package/dist/esm/v1/primitives/display/Avatar/Avatar.js +120 -0
  87. package/dist/esm/v1/primitives/display/Avatar/Avatar.js.map +1 -0
  88. package/dist/esm/v1/primitives/display/Badge/Badge.js +23 -0
  89. package/dist/esm/v1/primitives/display/Badge/Badge.js.map +1 -0
  90. package/dist/esm/v1/primitives/display/Card/Card.js +22 -0
  91. package/dist/esm/v1/primitives/display/Card/Card.js.map +1 -0
  92. package/dist/esm/v1/primitives/display/FilterChips/FilterChips.js +45 -0
  93. package/dist/esm/v1/primitives/display/FilterChips/FilterChips.js.map +1 -0
  94. package/dist/esm/v1/primitives/display/Kpi/Kpi.js +103 -0
  95. package/dist/esm/v1/primitives/display/Kpi/Kpi.js.map +1 -0
  96. package/dist/esm/v1/primitives/display/Notice/Notice.js +71 -0
  97. package/dist/esm/v1/primitives/display/Notice/Notice.js.map +1 -0
  98. package/dist/esm/v1/primitives/display/Person/Person.js +14 -0
  99. package/dist/esm/v1/primitives/display/Person/Person.js.map +1 -0
  100. package/dist/esm/v1/primitives/forms/Checkbox/Checkbox.js +10 -5
  101. package/dist/esm/v1/primitives/forms/Checkbox/Checkbox.js.map +1 -1
  102. package/dist/esm/v1/primitives/forms/DateInput/DateInput.js +150 -0
  103. package/dist/esm/v1/primitives/forms/DateInput/DateInput.js.map +1 -0
  104. package/dist/esm/v1/primitives/forms/LookupInput/LookupInput.js.map +1 -1
  105. package/dist/esm/v1/primitives/forms/SearchInput/SearchInput.js +43 -0
  106. package/dist/esm/v1/primitives/forms/SearchInput/SearchInput.js.map +1 -0
  107. package/dist/esm/v1/primitives/forms/SelectInput/SelectInput.js +190 -12
  108. package/dist/esm/v1/primitives/forms/SelectInput/SelectInput.js.map +1 -1
  109. package/dist/esm/v1/primitives/forms/TextArea/TextArea.js.map +1 -1
  110. package/dist/esm/v1/primitives/forms/field.js +4 -2
  111. package/dist/esm/v1/primitives/forms/field.js.map +1 -1
  112. package/dist/esm/v1/primitives/lists/ListItem/ListItem.js +2 -2
  113. package/dist/esm/v1/primitives/lists/ListItem/ListItem.js.map +1 -1
  114. package/dist/esm/v1/primitives/navigation/Tabs/Tabs.js +96 -0
  115. package/dist/esm/v1/primitives/navigation/Tabs/Tabs.js.map +1 -0
  116. package/dist/style.components.css +1 -1
  117. package/dist/style.css +1 -1
  118. package/dist/style.layered.css +1 -1
  119. package/dist/tailwind.css +24 -0
  120. package/dist/theme-boot.js +1 -0
  121. package/dist/theme.css +10 -3
  122. package/dist/tokens.css +119 -0
  123. package/dist/types/legacy/components/atoms/InputData/InputData.d.ts +4 -1
  124. package/dist/types/legacy/components/charts/Charts.d.ts +58 -5
  125. package/dist/types/legacy/components/layout/Layout/Layout.d.ts +7 -20
  126. package/dist/types/legacy/components/layout/Sidebar/Sidebar.d.ts +13 -26
  127. package/dist/types/legacy/components/molecules/ColumnPicker/ColumnPicker.d.ts +56 -3
  128. package/dist/types/legacy/components/molecules/DataTable/DataTable.d.ts +72 -7
  129. package/dist/types/legacy/components/molecules/UserAvatar/UserAvatar.d.ts +4 -5
  130. package/dist/types/legacy/components/ui/Avisos.d.ts +6 -16
  131. package/dist/types/legacy/components/ui/CabecalhoPagina.d.ts +6 -20
  132. package/dist/types/legacy/components/ui/CaixaPesquisa.d.ts +2 -4
  133. package/dist/types/legacy/components/ui/Confirmacao.d.ts +3 -10
  134. package/dist/types/legacy/components/ui/Escolha.d.ts +5 -15
  135. package/dist/types/legacy/components/ui/FaixaAviso.d.ts +2 -6
  136. package/dist/types/legacy/components/ui/Separadores.d.ts +3 -10
  137. package/dist/types/legacy/components/ui/Ui.d.ts +12 -54
  138. package/dist/types/legacy/components/ui/painelFlutuante.d.ts +6 -10
  139. package/dist/types/legacy/exports/atoms.d.ts +1 -1
  140. package/dist/types/legacy/exports/charts.d.ts +2 -2
  141. package/dist/types/legacy/exports/hooks.d.ts +2 -2
  142. package/dist/types/legacy/exports/molecules.d.ts +2 -2
  143. package/dist/types/v1/capabilities/overlay/useFloatingPanel.d.ts +20 -0
  144. package/dist/types/v1/capabilities/theme/useIsDark.d.ts +10 -0
  145. package/dist/types/v1/capabilities/theme/useTheme.d.ts +29 -0
  146. package/dist/types/v1/components/data/Pagination/Pagination.d.ts +33 -0
  147. package/dist/types/v1/components/feedback/Toast/Toast.d.ts +51 -0
  148. package/dist/types/v1/components/forms/FormField/FormField.d.ts +3 -3
  149. package/dist/types/v1/components/forms/FormGrid/FormGrid.d.ts +2 -0
  150. package/dist/types/v1/components/layout/AppShell/AppShell.d.ts +35 -0
  151. package/dist/types/v1/components/layout/Page/Page.d.ts +23 -0
  152. package/dist/types/v1/components/layout/PageHeader/PageHeader.d.ts +35 -0
  153. package/dist/types/v1/components/layout/SideNav/SideNav.d.ts +92 -0
  154. package/dist/types/v1/components/layout/navTrail.d.ts +15 -0
  155. package/dist/types/v1/components/lists/ListFinder/ListFinder.d.ts +1 -1
  156. package/dist/types/v1/components/overlays/ConfirmDialog/ConfirmDialog.d.ts +59 -0
  157. package/dist/types/v1/components/overlays/Dialog/Dialog.d.ts +6 -3
  158. package/dist/types/v1/components/overlays/Tooltip/Tooltip.d.ts +34 -0
  159. package/dist/types/v1/components/overlays/Tooltip/TooltipLayer.d.ts +18 -0
  160. package/dist/types/v1/components/overlays/Tooltip/TooltipPanel.d.ts +23 -0
  161. package/dist/types/v1/components/overlays/topLayer.d.ts +23 -0
  162. package/dist/types/v1/components/tables/PaginatedTable/PaginatedTable.d.ts +1 -1
  163. package/dist/types/v1/components/tables/Table/Table.d.ts +1 -1
  164. package/dist/types/v1/foundations/icons/icons.d.ts +20 -0
  165. package/dist/types/v1/index.d.ts +43 -1
  166. package/dist/types/v1/primitives/buttons/Button/Button.d.ts +22 -5
  167. package/dist/types/v1/primitives/buttons/SegmentedControl/SegmentedControl.d.ts +28 -0
  168. package/dist/types/v1/primitives/buttons/SegmentedControl/segmentedStyles.d.ts +16 -0
  169. package/dist/types/v1/primitives/display/Avatar/Avatar.d.ts +30 -0
  170. package/dist/types/v1/primitives/display/Badge/Badge.d.ts +25 -0
  171. package/dist/types/v1/primitives/display/Card/Card.d.ts +22 -0
  172. package/dist/types/v1/primitives/display/FilterChips/FilterChips.d.ts +33 -0
  173. package/dist/types/v1/primitives/display/Kpi/Kpi.d.ts +68 -0
  174. package/dist/types/v1/primitives/display/Notice/Notice.d.ts +29 -0
  175. package/dist/types/v1/primitives/display/Person/Person.d.ts +15 -0
  176. package/dist/types/v1/primitives/forms/Checkbox/Checkbox.d.ts +7 -0
  177. package/dist/types/v1/primitives/forms/DateInput/DateInput.d.ts +43 -0
  178. package/dist/types/v1/primitives/forms/LookupInput/LookupInput.d.ts +3 -0
  179. package/dist/types/v1/primitives/forms/SearchInput/SearchInput.d.ts +23 -0
  180. package/dist/types/v1/primitives/forms/SelectInput/SelectInput.d.ts +61 -10
  181. package/dist/types/v1/primitives/forms/TextArea/TextArea.d.ts +3 -0
  182. package/dist/types/v1/primitives/forms/field.d.ts +2 -0
  183. package/dist/types/v1/primitives/lists/ListItem/ListItem.d.ts +2 -1
  184. package/dist/types/v1/primitives/navigation/Tabs/Tabs.d.ts +58 -0
  185. package/package.json +3 -3
  186. package/dist/esm/legacy/components/atoms/Tooltip/Tooltip.css +0 -17
  187. package/dist/esm/legacy/components/atoms/Tooltip/Tooltip.js +0 -41
  188. package/dist/esm/legacy/components/atoms/Tooltip/Tooltip.js.map +0 -1
  189. package/dist/esm/legacy/components/molecules/Search/Search.css +0 -18
  190. package/dist/esm/legacy/components/molecules/Search/Search.js +0 -30
  191. package/dist/esm/legacy/components/molecules/Search/Search.js.map +0 -1
  192. package/dist/esm/legacy/hooks/useTheme.js +0 -39
  193. package/dist/esm/legacy/hooks/useTheme.js.map +0 -1
  194. package/dist/esm/v1/primitives/lists/ListItem/ListCheckbox.js +0 -28
  195. package/dist/esm/v1/primitives/lists/ListItem/ListCheckbox.js.map +0 -1
  196. package/dist/types/legacy/components/atoms/Tooltip/Tooltip.d.ts +0 -13
  197. package/dist/types/legacy/components/molecules/Search/Search.d.ts +0 -7
  198. package/dist/types/legacy/hooks/useTheme.d.ts +0 -17
  199. package/dist/types/v1/primitives/lists/ListItem/ListCheckbox.d.ts +0 -14
@@ -1,227 +1,38 @@
1
- import { jsxs, jsx, Fragment as Fragment$1 } from "react/jsx-runtime";
2
- import { useState, useEffect, Fragment } from "react";
3
- import { useLocation, NavLink } from "react-router-dom";
4
- const ChevronLeft = ({ size = 24, className }) => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: /* @__PURE__ */ jsx("path", { d: "m15 18-6-6 6-6" }) });
5
- const ChevronRight = ({ size = 24, className }) => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" }) });
6
- const ChevronDown = ({ size = 24, className }) => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" }) });
7
- const ExternalLink = ({ size = 24, className }) => /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
8
- /* @__PURE__ */ jsx("path", { d: "M15 3h6v6" }),
9
- /* @__PURE__ */ jsx("path", { d: "M10 14 21 3" }),
10
- /* @__PURE__ */ jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" })
11
- ] });
12
- const LogOut = ({ size = 24, className }) => /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
13
- /* @__PURE__ */ jsx("path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }),
14
- /* @__PURE__ */ jsx("polyline", { points: "16 17 21 12 16 7" }),
15
- /* @__PURE__ */ jsx("line", { x1: "21", x2: "9", y1: "12", y2: "12" })
16
- ] });
17
- const Globe = ({ size = 24, className }) => /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
18
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
19
- /* @__PURE__ */ jsx("path", { d: "M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" }),
20
- /* @__PURE__ */ jsx("path", { d: "M2 12h20" })
21
- ] });
22
- const Sun = ({ size = 24, className }) => /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
23
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "4" }),
24
- /* @__PURE__ */ jsx("path", { d: "M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41" })
25
- ] });
26
- const Moon = ({ size = 24, className }) => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: /* @__PURE__ */ jsx("path", { d: "M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9z" }) });
27
- const Monitor = ({ size = 24, className }) => /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
28
- /* @__PURE__ */ jsx("rect", { width: "20", height: "14", x: "2", y: "3", rx: "2" }),
29
- /* @__PURE__ */ jsx("path", { d: "M8 21h8M12 17v4" })
30
- ] });
31
- function formatarDeploy(valor) {
32
- const d = valor instanceof Date ? valor : new Date(valor);
33
- if (Number.isNaN(d.getTime())) return "";
34
- const dois = (n) => String(n).padStart(2, "0");
35
- return `${dois(d.getDate())}/${dois(d.getMonth() + 1)}/${d.getFullYear()}, ${dois(d.getHours())}:${dois(d.getMinutes())}:${dois(d.getSeconds())}`;
36
- }
1
+ import { jsx } from "react/jsx-runtime";
2
+ import SideNav from "../../../../v1/components/layout/SideNav/SideNav.js";
3
+ const menuV1 = (menus) => menus.map(({ badge, ...item }) => ({ ...item, end: item.end ?? item.to === "/", badges: badge ? [{ count: badge }] : void 0 }));
4
+ const labelsV1 = (p) => ({
5
+ logout: p.logoutLabel ?? "Logout",
6
+ theme: p.themeLabels?.label ?? "Theme",
7
+ light: p.themeLabels?.light ?? "Light",
8
+ dark: p.themeLabels?.dark ?? "Dark",
9
+ system: p.themeLabels?.system ?? "System",
10
+ deployedAt: p.deployedAtLabel ?? "Último deploy"
11
+ });
37
12
  const Sidebar = ({
38
13
  isOpen = true,
39
14
  setIsOpen,
40
15
  menus,
41
- groupLabels = {},
42
- appTitle,
43
- avatar,
44
- onLogout,
45
- logoutLabel = "Logout",
46
- languages,
47
16
  currentLang,
48
- onLanguageChange,
49
- theme,
50
- onThemeChange,
17
+ logoutLabel,
51
18
  themeLabels,
52
- footer,
53
- deployedAt,
54
- deployedAtLabel = "Último deploy"
55
- }) => {
56
- const [isHovered, setIsHovered] = useState(false);
57
- const isExpanded = isOpen || isHovered;
58
- const GROUPS = Array.from(new Set(menus.map((m) => m.group).filter(Boolean)));
59
- const routeGroupMap = Object.fromEntries(
60
- menus.filter((m) => m.group).map((m) => [m.to, m.group])
61
- );
62
- const location = useLocation();
63
- const buildCollapsed = (pathname) => {
64
- const base = window.innerHeight < 950 ? Object.fromEntries(GROUPS.map((g) => [g, true])) : {};
65
- const activeGroup = Object.entries(routeGroupMap).find(([p]) => pathname.includes(p))?.[1];
66
- if (activeGroup) base[activeGroup] = false;
67
- return base;
68
- };
69
- const [collapsedGroups, setCollapsedGroups] = useState(
70
- () => buildCollapsed(location.pathname)
71
- );
72
- const toggleGroup = (group) => setCollapsedGroups((prev) => ({ ...prev, [group]: !prev[group] }));
73
- const cycleLang = () => {
74
- if (!languages?.length || !onLanguageChange) return;
75
- const idx = languages.findIndex((l) => l.code === currentLang);
76
- const next = languages[(idx + 1) % languages.length];
77
- if (next) onLanguageChange(next.code);
78
- };
79
- const themeOptions = [
80
- { val: "light", Icon: Sun, label: themeLabels?.light ?? "Light" },
81
- { val: "dark", Icon: Moon, label: themeLabels?.dark ?? "Dark" },
82
- { val: "system", Icon: Monitor, label: themeLabels?.system ?? "System" }
83
- ];
84
- const ThemeIcon = theme === "light" ? Sun : theme === "dark" ? Moon : Monitor;
85
- const cycleTheme = () => {
86
- if (!onThemeChange) return;
87
- const order = ["light", "dark", "system"];
88
- const idx = order.indexOf(theme ?? "system");
89
- onThemeChange(order[(idx + 1) % order.length]);
90
- };
91
- useEffect(() => {
92
- const onResize = () => setCollapsedGroups(buildCollapsed(location.pathname));
93
- window.addEventListener("resize", onResize);
94
- return () => window.removeEventListener("resize", onResize);
95
- }, [location.pathname]);
96
- useEffect(() => {
97
- const activeGroup = Object.entries(routeGroupMap).find(
98
- ([p]) => location.pathname.includes(p)
99
- )?.[1];
100
- if (activeGroup) setCollapsedGroups((prev) => ({ ...prev, [activeGroup]: false }));
101
- }, [location.pathname]);
102
- return /* @__PURE__ */ jsxs(
103
- "aside",
104
- {
105
- onMouseEnter: () => !isOpen && setIsHovered(true),
106
- onMouseLeave: () => setIsHovered(false),
107
- className: `bg-proef-navy text-white h-screen flex flex-col fixed left-0 top-0 z-40 transition-all duration-300 border-r border-white/10 overflow-hidden ${isExpanded ? "w-64 translate-x-0" : "w-20 sm:translate-x-0 -translate-x-full"}`,
108
- children: [
109
- /* @__PURE__ */ jsxs("div", { className: `px-4 flex flex-row items-center h-16 ${isExpanded ? "justify-between" : "justify-center"}`, children: [
110
- isExpanded && /* @__PURE__ */ jsxs("div", { className: "flex flex-col pl-2", children: [
111
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
112
- /* @__PURE__ */ jsx("span", { className: "text-3xl font-black text-white tracking-tighter", children: "proef" }),
113
- /* @__PURE__ */ jsx("div", { className: "w-2 h-2 rounded-full bg-proef-turquoise mt-3 animate-pulse" })
114
- ] }),
115
- appTitle && /* @__PURE__ */ jsx("span", { className: "text-[10px] font-black uppercase tracking-[0.3em] text-white/50 mt-1 pl-1", children: appTitle })
116
- ] }),
117
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
118
- avatar && /* @__PURE__ */ jsx("div", { className: "cursor-help flex-shrink-0", children: avatar }),
119
- setIsOpen && isExpanded && // isOpen: fixa → colapsa (ChevronLeft). Colapsada+hover: fixa de volta (ChevronRight).
120
- /* @__PURE__ */ jsx("button", { onClick: () => setIsOpen(!isOpen), title: isOpen ? void 0 : "Fixar", className: "appearance-none border-0 cursor-pointer text-white/40 hover:text-white transition-colors p-1.5 bg-white/5 rounded-lg hover:bg-white/10", children: isOpen ? /* @__PURE__ */ jsx(ChevronLeft, { size: 16 }) : /* @__PURE__ */ jsx(ChevronRight, { size: 16 }) })
121
- ] })
122
- ] }),
123
- /* @__PURE__ */ jsx("nav", { className: "flex-1 overflow-y-auto overflow-x-hidden pt-2 transition-opacity duration-300", children: menus.map((item, i) => {
124
- const prevGroup = menus[i - 1]?.group;
125
- const currGroup = item.group;
126
- const showGroupHeader = currGroup && currGroup !== prevGroup;
127
- const isGroupCollapsed = !!currGroup && !!collapsedGroups[currGroup];
128
- return /* @__PURE__ */ jsxs(Fragment, { children: [
129
- showGroupHeader && isExpanded && /* @__PURE__ */ jsxs("button", { onClick: () => toggleGroup(currGroup), className: "w-full px-6 pt-5 pb-1.5 text-left group/grp appearance-none bg-transparent border-0 cursor-pointer", children: [
130
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
131
- /* @__PURE__ */ jsx("span", { className: "text-[9px] font-black uppercase tracking-[0.25em] text-white/30 group-hover/grp:text-white/50 transition-colors", children: groupLabels[currGroup] ?? currGroup }),
132
- /* @__PURE__ */ jsx(ChevronDown, { size: 10, className: `text-white/30 group-hover/grp:text-white/50 transition-all ${isGroupCollapsed ? "-rotate-90" : ""}` })
133
- ] }),
134
- /* @__PURE__ */ jsx("div", { className: "mt-1 h-px bg-white/10" })
135
- ] }),
136
- showGroupHeader && !isExpanded && /* @__PURE__ */ jsx("div", { className: "mx-auto w-8 my-3 h-px bg-white/15" }),
137
- !isGroupCollapsed && item.external && /* @__PURE__ */ jsxs(
138
- "a",
139
- {
140
- href: item.to,
141
- target: "_blank",
142
- rel: "noreferrer",
143
- title: !isExpanded ? item.label : void 0,
144
- onClick: () => {
145
- if (window.innerWidth < 640 && setIsOpen) setIsOpen(false);
146
- },
147
- className: `
148
- flex items-center gap-4 transition-all duration-300 rounded-lg mx-2 no-underline
149
- ${isExpanded ? "px-6 py-2.5" : "px-0 py-2.5 justify-center"}
150
- text-white/50 hover:bg-white/5 hover:text-white
151
- `,
152
- children: [
153
- /* @__PURE__ */ jsx("div", { className: "relative flex-shrink-0", children: /* @__PURE__ */ jsx(item.icon, { size: 20 }) }),
154
- isExpanded && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 flex-1 min-w-0", children: [
155
- /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold truncate", children: item.label }),
156
- /* @__PURE__ */ jsx(ExternalLink, { size: 12, className: "ml-auto flex-shrink-0 text-white/30" })
157
- ] })
158
- ]
159
- }
160
- ),
161
- !isGroupCollapsed && !item.external && /* @__PURE__ */ jsx(
162
- NavLink,
163
- {
164
- to: item.to,
165
- end: item.end ?? item.to === "/",
166
- title: !isExpanded ? item.label : void 0,
167
- onClick: () => {
168
- if (window.innerWidth < 640 && setIsOpen) setIsOpen(false);
169
- },
170
- className: ({ isActive }) => `
171
- flex items-center gap-4 transition-all duration-300 rounded-lg mx-2
172
- ${isExpanded ? "px-6 py-2.5" : "px-0 py-2.5 justify-center"}
173
- ${isActive ? "bg-proef-turquoise/15 text-proef-turquoise font-semibold" : "text-white/50 hover:bg-white/5 hover:text-white"}
174
- `,
175
- children: ({ isActive }) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
176
- /* @__PURE__ */ jsxs("div", { className: "relative flex-shrink-0", children: [
177
- /* @__PURE__ */ jsx(item.icon, { size: 20, className: isActive ? "text-proef-turquoise drop-shadow-[0_0_6px_rgba(0,230,200,0.6)]" : "" }),
178
- item.badge != null && item.badge > 0 && !isExpanded && /* @__PURE__ */ jsx("span", { className: "absolute -top-1 -right-1 w-2 h-2 rounded-full bg-amber-400" })
179
- ] }),
180
- isExpanded && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 flex-1 min-w-0", children: [
181
- /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold truncate", children: item.label }),
182
- item.badge != null && item.badge > 0 && /* @__PURE__ */ jsx("span", { className: "ml-auto flex-shrink-0 bg-amber-400 text-proef-navy text-[10px] font-black rounded-full px-1.5 py-0.5 min-w-[18px] text-center leading-none", children: item.badge })
183
- ] })
184
- ] })
185
- }
186
- )
187
- ] }, item.to);
188
- }) }),
189
- /* @__PURE__ */ jsxs("div", { className: `mt-auto border-t border-white/10 px-2 py-3 ${isExpanded ? "space-y-2" : "flex flex-col items-center gap-3"}`, children: [
190
- footer && /* @__PURE__ */ jsx("div", { className: isExpanded ? "" : "w-full flex justify-center", children: footer(isExpanded) }),
191
- onThemeChange && (isExpanded ? /* @__PURE__ */ jsxs("div", { children: [
192
- /* @__PURE__ */ jsx("p", { className: "px-1 pb-1 text-[8px] font-black uppercase tracking-[0.25em] text-white/30", children: themeLabels?.label ?? "Theme" }),
193
- /* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-1 p-1 bg-white/5 rounded-lg border border-white/5", children: themeOptions.map((opt) => /* @__PURE__ */ jsxs(
194
- "button",
195
- {
196
- onClick: () => onThemeChange(opt.val),
197
- title: opt.label,
198
- "aria-pressed": theme === opt.val,
199
- className: `appearance-none bg-transparent border-0 cursor-pointer flex flex-col items-center gap-1 py-1.5 rounded-md text-[8px] font-black uppercase tracking-wider transition-all ${theme === opt.val ? "bg-proef-turquoise/15 text-proef-turquoise" : "text-white/40 hover:text-white/70 hover:bg-white/5"}`,
200
- children: [
201
- /* @__PURE__ */ jsx(opt.Icon, { size: 14 }),
202
- opt.label
203
- ]
204
- },
205
- opt.val
206
- )) })
207
- ] }) : /* @__PURE__ */ jsx("button", { onClick: cycleTheme, title: themeLabels?.label ?? "Theme", className: "appearance-none bg-transparent border-0 cursor-pointer p-2 text-white/30 hover:text-proef-turquoise transition-colors rounded-lg hover:bg-white/5", children: /* @__PURE__ */ jsx(ThemeIcon, { size: 18 }) })),
208
- languages && languages.length > 0 && (isExpanded ? /* @__PURE__ */ jsx("div", { className: "flex gap-1", children: languages.map((l) => /* @__PURE__ */ jsx(
209
- "button",
210
- {
211
- onClick: () => onLanguageChange?.(l.code),
212
- className: `appearance-none bg-transparent cursor-pointer flex-1 py-1.5 text-[10px] font-black uppercase tracking-widest border transition-all rounded-md ${currentLang === l.code ? "text-proef-turquoise border-proef-turquoise/40" : "text-white/40 border-white/5 hover:text-white hover:border-white/20"}`,
213
- children: l.label
214
- },
215
- l.code
216
- )) }) : /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx("button", { onClick: cycleLang, title: currentLang?.toUpperCase(), className: "appearance-none bg-transparent border-0 cursor-pointer p-2 text-white/30 hover:text-proef-turquoise transition-colors rounded-lg hover:bg-white/5", children: /* @__PURE__ */ jsx(Globe, { size: 18 }) }) })),
217
- isExpanded ? /* @__PURE__ */ jsx("button", { onClick: () => onLogout?.(), className: "appearance-none bg-transparent cursor-pointer w-full text-center py-2.5 text-[10px] font-black uppercase tracking-widest text-white/40 hover:text-proef-turquoise transition-all border border-white/5 hover:border-proef-turquoise/30", children: logoutLabel }) : /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx("button", { onClick: () => onLogout?.(), title: logoutLabel, className: "appearance-none bg-transparent border-0 cursor-pointer p-2 text-white/30 hover:text-proef-turquoise transition-colors rounded-lg hover:bg-white/5", children: /* @__PURE__ */ jsx(LogOut, { size: 18 }) }) }),
218
- deployedAt != null && isExpanded && /* @__PURE__ */ jsx("div", { title: deployedAtLabel, className: "text-center text-[10px] tabular-nums text-white/25 select-text", children: formatarDeploy(deployedAt) })
219
- ] })
220
- ]
221
- }
222
- );
223
- };
19
+ deployedAtLabel,
20
+ ...rest
21
+ }) => /* @__PURE__ */ jsx(
22
+ SideNav,
23
+ {
24
+ ...rest,
25
+ menu: menuV1(menus),
26
+ currentLanguage: currentLang,
27
+ labels: labelsV1({ logoutLabel, themeLabels, deployedAtLabel }),
28
+ open: isOpen,
29
+ onOpenChange: setIsOpen ?? (() => {
30
+ })
31
+ }
32
+ );
224
33
  export {
225
- Sidebar as default
34
+ Sidebar as default,
35
+ labelsV1,
36
+ menuV1
226
37
  };
227
38
  //# sourceMappingURL=Sidebar.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Sidebar.js","sources":["../../../../../../src/legacy/components/layout/Sidebar/Sidebar.tsx"],"sourcesContent":["import React, { useState, Fragment, useEffect } from 'react'\r\nimport { NavLink, useLocation } from 'react-router-dom'\r\n\r\n// ── Inline icons (no lucide-react dependency in common-ui) ────────────────\r\ntype IconProps = { size?: number; className?: string }\r\n\r\nconst ChevronLeft = ({ size = 24, className }: IconProps) => (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\r\n <path d=\"m15 18-6-6 6-6\" />\r\n </svg>\r\n)\r\n\r\nconst ChevronRight = ({ size = 24, className }: IconProps) => (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\r\n <path d=\"m9 18 6-6-6-6\" />\r\n </svg>\r\n)\r\n\r\nconst ChevronDown = ({ size = 24, className }: IconProps) => (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\r\n <path d=\"m6 9 6 6 6-6\" />\r\n </svg>\r\n)\r\n\r\nconst ExternalLink = ({ size = 24, className }: IconProps) => (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\r\n <path d=\"M15 3h6v6\" />\r\n <path d=\"M10 14 21 3\" />\r\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\r\n </svg>\r\n)\r\n\r\nconst LogOut = ({ size = 24, className }: IconProps) => (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\r\n <path d=\"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4\" />\r\n <polyline points=\"16 17 21 12 16 7\" />\r\n <line x1=\"21\" x2=\"9\" y1=\"12\" y2=\"12\" />\r\n </svg>\r\n)\r\n\r\nconst Globe = ({ size = 24, className }: IconProps) => (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\r\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\r\n <path d=\"M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z\" />\r\n <path d=\"M2 12h20\" />\r\n </svg>\r\n)\r\n\r\nconst Sun = ({ size = 24, className }: IconProps) => (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\r\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\r\n <path d=\"M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41\" />\r\n </svg>\r\n)\r\n\r\nconst Moon = ({ size = 24, className }: IconProps) => (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\r\n <path d=\"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9z\" />\r\n </svg>\r\n)\r\n\r\nconst Monitor = ({ size = 24, className }: IconProps) => (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\r\n <rect width=\"20\" height=\"14\" x=\"2\" y=\"3\" rx=\"2\" />\r\n <path d=\"M8 21h8M12 17v4\" />\r\n </svg>\r\n)\r\n\r\n/** @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy. */\r\nexport type SidebarTheme = 'light' | 'dark' | 'system'\r\n\r\n/** @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy. */\r\nexport interface SidebarLanguage {\r\n code: string\r\n label: string\r\n}\r\n\r\n/** @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy. */\r\nexport interface SidebarMenuItem {\r\n to: string\r\n icon: React.ComponentType<{ size?: number; className?: string }>\r\n label: string\r\n group?: string\r\n end?: boolean\r\n /** Contador opcional (ex: aprovações pendentes). Igual ao badge do Sidebar dos Tickets. */\r\n badge?: number\r\n /**\r\n * Destino fora da aplicação (SharePoint, portal antigo, etc.): abre em\r\n * separador novo em vez de navegar pelo router. Sem isto, um URL absoluto\r\n * ia parar ao NavLink, que o trata como rota interna e dá página em branco.\r\n */\r\n external?: boolean\r\n}\r\n\r\n/** @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy. */\r\nexport interface SidebarProps {\r\n isOpen?: boolean\r\n setIsOpen?: (isOpen: boolean) => void\r\n menus: SidebarMenuItem[]\r\n groupLabels?: Record<string, string>\r\n appTitle?: string\r\n avatar?: React.ReactNode\r\n onLogout?: () => void\r\n logoutLabel?: string\r\n /** Selector de idioma no rodapé da sidebar. Só aparece se `languages` vier. */\r\n languages?: SidebarLanguage[]\r\n currentLang?: string\r\n onLanguageChange?: (code: string) => void\r\n /** Selector de tema (light/dark/system) no rodapé. Só aparece se `onThemeChange` vier.\r\n * O common-ui só renderiza a UI + chama o callback — aplicar a classe `.dark`\r\n * no <html> é responsabilidade da app (o seu gestor de tema). */\r\n theme?: SidebarTheme\r\n onThemeChange?: (theme: SidebarTheme) => void\r\n themeLabels?: { label?: string; light?: string; dark?: string; system?: string }\r\n /** Slot extra no topo do rodapé (acima de tema/idioma/logout). Render-prop\r\n * com o estado expandido → ex: filtro global (AgendamentoEDP → AoFilterDropdown). */\r\n footer?: (isExpanded: boolean) => React.ReactNode\r\n /**\r\n * Quando este build foi feito — aparece por baixo do logout.\r\n *\r\n * Serve para responder a \"isto já tem a correcção?\": diz a idade do código\r\n * que o browser está mesmo a correr, e não a que o servidor tem. A app é que\r\n * decide a QUEM o mostra (tipicamente só admins) — passar a prop é mostrá-la.\r\n */\r\n deployedAt?: string | number | Date\r\n /** Tooltip do rodapé, para a app o traduzir. */\r\n deployedAtLabel?: string\r\n}\r\n\r\n/**\r\n * `DD/MM/AAAA, HH:MM:SS` na hora local de quem lê.\r\n *\r\n * Escrito à mão e não com `toLocaleString`: o formato do rodapé não pode\r\n * mudar com a lingua escolhida no selector mesmo ao lado — é um carimbo, e\r\n * lê-se sempre da mesma maneira. Data inválida não mostra nada.\r\n */\r\nfunction formatarDeploy(valor: string | number | Date): string {\r\n const d = valor instanceof Date ? valor : new Date(valor)\r\n if (Number.isNaN(d.getTime())) return ''\r\n const dois = (n: number) => String(n).padStart(2, '0')\r\n return `${dois(d.getDate())}/${dois(d.getMonth() + 1)}/${d.getFullYear()}, ${dois(d.getHours())}:${dois(d.getMinutes())}:${dois(d.getSeconds())}`\r\n}\r\n\r\n/** @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy. */\r\nconst Sidebar = ({\r\n isOpen = true,\r\n setIsOpen,\r\n menus,\r\n groupLabels = {},\r\n appTitle,\r\n avatar,\r\n onLogout,\r\n logoutLabel = 'Logout',\r\n languages,\r\n currentLang,\r\n onLanguageChange,\r\n theme,\r\n onThemeChange,\r\n themeLabels,\r\n footer,\r\n deployedAt,\r\n deployedAtLabel = 'Último deploy',\r\n}: SidebarProps) => {\r\n const [isHovered, setIsHovered] = useState(false)\r\n const isExpanded = isOpen || isHovered\r\n\r\n // ── Nav groups — derived from the injected menus ─────────────────────────\r\n const GROUPS = Array.from(new Set(menus.map((m) => m.group).filter(Boolean))) as string[]\r\n const routeGroupMap: Record<string, string> = Object.fromEntries(\r\n menus.filter((m) => m.group).map((m) => [m.to, m.group as string])\r\n )\r\n\r\n const location = useLocation()\r\n\r\n const buildCollapsed = (pathname: string) => {\r\n const base =\r\n window.innerHeight < 950\r\n ? Object.fromEntries(GROUPS.map((g) => [g, true]))\r\n : ({} as Record<string, boolean>)\r\n const activeGroup = Object.entries(routeGroupMap).find(([p]) => pathname.includes(p))?.[1]\r\n if (activeGroup) base[activeGroup] = false\r\n return base\r\n }\r\n\r\n const [collapsedGroups, setCollapsedGroups] = useState<Record<string, boolean>>(() =>\r\n buildCollapsed(location.pathname)\r\n )\r\n const toggleGroup = (group: string) =>\r\n setCollapsedGroups((prev) => ({ ...prev, [group]: !prev[group] }))\r\n\r\n // Colapsada: 1 botão que roda p/ o próximo idioma (não há espaço p/ segmentos).\r\n const cycleLang = () => {\r\n if (!languages?.length || !onLanguageChange) return\r\n const idx = languages.findIndex((l) => l.code === currentLang)\r\n const next = languages[(idx + 1) % languages.length]\r\n if (next) onLanguageChange(next.code)\r\n }\r\n\r\n // Seletor de tema (light/dark/system) — derivado do Sidebar do Tickets.\r\n const themeOptions: { val: SidebarTheme; Icon: React.ComponentType<IconProps>; label: string }[] = [\r\n { val: 'light', Icon: Sun, label: themeLabels?.light ?? 'Light' },\r\n { val: 'dark', Icon: Moon, label: themeLabels?.dark ?? 'Dark' },\r\n { val: 'system', Icon: Monitor, label: themeLabels?.system ?? 'System' },\r\n ]\r\n const ThemeIcon = theme === 'light' ? Sun : theme === 'dark' ? Moon : Monitor\r\n const cycleTheme = () => {\r\n if (!onThemeChange) return\r\n const order: SidebarTheme[] = ['light', 'dark', 'system']\r\n const idx = order.indexOf((theme ?? 'system') as SidebarTheme)\r\n onThemeChange(order[(idx + 1) % order.length])\r\n }\r\n\r\n useEffect(() => {\r\n const onResize = () => setCollapsedGroups(buildCollapsed(location.pathname))\r\n window.addEventListener('resize', onResize)\r\n return () => window.removeEventListener('resize', onResize)\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [location.pathname])\r\n\r\n useEffect(() => {\r\n const activeGroup = Object.entries(routeGroupMap).find(([p]) =>\r\n location.pathname.includes(p)\r\n )?.[1]\r\n if (activeGroup) setCollapsedGroups((prev) => ({ ...prev, [activeGroup]: false }))\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [location.pathname])\r\n\r\n return (\r\n <aside\r\n onMouseEnter={() => !isOpen && setIsHovered(true)}\r\n onMouseLeave={() => setIsHovered(false)}\r\n className={`bg-proef-navy text-white h-screen flex flex-col fixed left-0 top-0 z-40 transition-all duration-300 border-r border-white/10 overflow-hidden ${isExpanded ? 'w-64 translate-x-0' : 'w-20 sm:translate-x-0 -translate-x-full'}`}>\r\n\r\n <div className={`px-4 flex flex-row items-center h-16 ${isExpanded ? 'justify-between' : 'justify-center'}`}>\r\n {isExpanded && (\r\n <div className=\"flex flex-col pl-2\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-3xl font-black text-white tracking-tighter\">proef</span>\r\n <div className=\"w-2 h-2 rounded-full bg-proef-turquoise mt-3 animate-pulse\" />\r\n </div>\r\n {appTitle && (\r\n <span className=\"text-[10px] font-black uppercase tracking-[0.3em] text-white/50 mt-1 pl-1\">{appTitle}</span>\r\n )}\r\n </div>\r\n )}\r\n <div className=\"flex items-center gap-2\">\r\n {avatar && (\r\n <div className=\"cursor-help flex-shrink-0\">{avatar}</div>\r\n )}\r\n {setIsOpen && isExpanded && (\r\n // isOpen: fixa → colapsa (ChevronLeft). Colapsada+hover: fixa de volta (ChevronRight).\r\n <button onClick={() => setIsOpen(!isOpen)} title={isOpen ? undefined : 'Fixar'} className=\"appearance-none border-0 cursor-pointer text-white/40 hover:text-white transition-colors p-1.5 bg-white/5 rounded-lg hover:bg-white/10\">\r\n {isOpen ? <ChevronLeft size={16} /> : <ChevronRight size={16} />}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n\r\n <nav className=\"flex-1 overflow-y-auto overflow-x-hidden pt-2 transition-opacity duration-300\">\r\n {menus.map((item, i) => {\r\n const prevGroup = menus[i - 1]?.group\r\n const currGroup = item.group\r\n const showGroupHeader = currGroup && currGroup !== prevGroup\r\n const isGroupCollapsed = !!currGroup && !!collapsedGroups[currGroup]\r\n\r\n return (\r\n <Fragment key={item.to}>\r\n {showGroupHeader && isExpanded && (\r\n <button onClick={() => toggleGroup(currGroup!)} className=\"w-full px-6 pt-5 pb-1.5 text-left group/grp appearance-none bg-transparent border-0 cursor-pointer\">\r\n <div className=\"flex items-center justify-between\">\r\n <span className=\"text-[9px] font-black uppercase tracking-[0.25em] text-white/30 group-hover/grp:text-white/50 transition-colors\">{groupLabels[currGroup!] ?? currGroup}</span>\r\n <ChevronDown size={10} className={`text-white/30 group-hover/grp:text-white/50 transition-all ${isGroupCollapsed ? '-rotate-90' : ''}`} />\r\n </div>\r\n <div className=\"mt-1 h-px bg-white/10\" />\r\n </button>\r\n )}\r\n {showGroupHeader && !isExpanded && <div className=\"mx-auto w-8 my-3 h-px bg-white/15\" />}\r\n {!isGroupCollapsed && item.external && (\r\n <a\r\n href={item.to}\r\n target=\"_blank\"\r\n rel=\"noreferrer\"\r\n title={!isExpanded ? item.label : undefined}\r\n onClick={() => { if (window.innerWidth < 640 && setIsOpen) setIsOpen(false) }}\r\n className={`\r\n flex items-center gap-4 transition-all duration-300 rounded-lg mx-2 no-underline\r\n ${isExpanded ? 'px-6 py-2.5' : 'px-0 py-2.5 justify-center'}\r\n text-white/50 hover:bg-white/5 hover:text-white\r\n `}\r\n >\r\n <div className=\"relative flex-shrink-0\">\r\n <item.icon size={20} />\r\n </div>\r\n {isExpanded && (\r\n <div className=\"flex items-center gap-1.5 flex-1 min-w-0\">\r\n <span className=\"text-sm font-semibold truncate\">{item.label}</span>\r\n <ExternalLink size={12} className=\"ml-auto flex-shrink-0 text-white/30\" />\r\n </div>\r\n )}\r\n </a>\r\n )}\r\n {!isGroupCollapsed && !item.external && (\r\n <NavLink\r\n to={item.to}\r\n end={item.end ?? item.to === '/'}\r\n title={!isExpanded ? item.label : undefined}\r\n onClick={() => { if (window.innerWidth < 640 && setIsOpen) setIsOpen(false) }}\r\n className={({ isActive }) => `\r\n flex items-center gap-4 transition-all duration-300 rounded-lg mx-2\r\n ${isExpanded ? 'px-6 py-2.5' : 'px-0 py-2.5 justify-center'}\r\n ${isActive ? 'bg-proef-turquoise/15 text-proef-turquoise font-semibold' : 'text-white/50 hover:bg-white/5 hover:text-white'}\r\n `}\r\n >\r\n {({ isActive }) => (\r\n <>\r\n <div className=\"relative flex-shrink-0\">\r\n <item.icon size={20} className={isActive ? 'text-proef-turquoise drop-shadow-[0_0_6px_rgba(0,230,200,0.6)]' : ''} />\r\n {item.badge != null && item.badge > 0 && !isExpanded && (\r\n <span className=\"absolute -top-1 -right-1 w-2 h-2 rounded-full bg-amber-400\" />\r\n )}\r\n </div>\r\n {isExpanded && (\r\n <div className=\"flex items-center gap-1.5 flex-1 min-w-0\">\r\n <span className=\"text-sm font-semibold truncate\">{item.label}</span>\r\n {item.badge != null && item.badge > 0 && (\r\n <span className=\"ml-auto flex-shrink-0 bg-amber-400 text-proef-navy text-[10px] font-black rounded-full px-1.5 py-0.5 min-w-[18px] text-center leading-none\">\r\n {item.badge}\r\n </span>\r\n )}\r\n </div>\r\n )}\r\n </>\r\n )}\r\n </NavLink>\r\n )}\r\n </Fragment>\r\n )\r\n })}\r\n </nav>\r\n\r\n <div className={`mt-auto border-t border-white/10 px-2 py-3 ${isExpanded ? 'space-y-2' : 'flex flex-col items-center gap-3'}`}>\r\n {/* Slot extra (ex: filtro global da app). Recebe o estado expandido. */}\r\n {footer && <div className={isExpanded ? '' : 'w-full flex justify-center'}>{footer(isExpanded)}</div>}\r\n\r\n {/* Seletor de tema (opcional). Expandida: grid Light/Dark/System; colapsada: 1 ícone que roda. */}\r\n {onThemeChange && (\r\n isExpanded ? (\r\n <div>\r\n <p className=\"px-1 pb-1 text-[8px] font-black uppercase tracking-[0.25em] text-white/30\">{themeLabels?.label ?? 'Theme'}</p>\r\n <div className=\"grid grid-cols-3 gap-1 p-1 bg-white/5 rounded-lg border border-white/5\">\r\n {themeOptions.map((opt) => (\r\n <button\r\n key={opt.val}\r\n onClick={() => onThemeChange(opt.val)}\r\n title={opt.label}\r\n aria-pressed={theme === opt.val}\r\n className={`appearance-none bg-transparent border-0 cursor-pointer flex flex-col items-center gap-1 py-1.5 rounded-md text-[8px] font-black uppercase tracking-wider transition-all ${theme === opt.val ? 'bg-proef-turquoise/15 text-proef-turquoise' : 'text-white/40 hover:text-white/70 hover:bg-white/5'}`}\r\n >\r\n <opt.Icon size={14} />\r\n {opt.label}\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n ) : (\r\n <button onClick={cycleTheme} title={themeLabels?.label ?? 'Theme'} className=\"appearance-none bg-transparent border-0 cursor-pointer p-2 text-white/30 hover:text-proef-turquoise transition-colors rounded-lg hover:bg-white/5\">\r\n <ThemeIcon size={18} />\r\n </button>\r\n )\r\n )}\r\n\r\n {/* Selector de idioma (opcional). Expandida: segmentos PT|EN; colapsada: 1 globo que roda. */}\r\n {languages && languages.length > 0 && (\r\n isExpanded ? (\r\n <div className=\"flex gap-1\">\r\n {languages.map((l) => (\r\n <button\r\n key={l.code}\r\n onClick={() => onLanguageChange?.(l.code)}\r\n className={`appearance-none bg-transparent cursor-pointer flex-1 py-1.5 text-[10px] font-black uppercase tracking-widest border transition-all rounded-md ${currentLang === l.code ? 'text-proef-turquoise border-proef-turquoise/40' : 'text-white/40 border-white/5 hover:text-white hover:border-white/20'}`}\r\n >\r\n {l.label}\r\n </button>\r\n ))}\r\n </div>\r\n ) : (\r\n <div className=\"flex justify-center\">\r\n <button onClick={cycleLang} title={currentLang?.toUpperCase()} className=\"appearance-none bg-transparent border-0 cursor-pointer p-2 text-white/30 hover:text-proef-turquoise transition-colors rounded-lg hover:bg-white/5\">\r\n <Globe size={18} />\r\n </button>\r\n </div>\r\n )\r\n )}\r\n\r\n {isExpanded ? (\r\n <button onClick={() => onLogout?.()} className=\"appearance-none bg-transparent cursor-pointer w-full text-center py-2.5 text-[10px] font-black uppercase tracking-widest text-white/40 hover:text-proef-turquoise transition-all border border-white/5 hover:border-proef-turquoise/30\">\r\n {logoutLabel}\r\n </button>\r\n ) : (\r\n <div className=\"flex justify-center\">\r\n <button onClick={() => onLogout?.()} title={logoutLabel} className=\"appearance-none bg-transparent border-0 cursor-pointer p-2 text-white/30 hover:text-proef-turquoise transition-colors rounded-lg hover:bg-white/5\">\r\n <LogOut size={18} />\r\n </button>\r\n </div>\r\n )}\r\n\r\n {/* Só com a sidebar aberta: no carril de 20px isto ficava ilegível\r\n ou cortado, e é informação de consulta, não um controlo. */}\r\n {deployedAt != null && isExpanded && (\r\n <div title={deployedAtLabel} className=\"text-center text-[10px] tabular-nums text-white/25 select-text\">\r\n {formatarDeploy(deployedAt)}\r\n </div>\r\n )}\r\n </div>\r\n </aside>\r\n )\r\n}\r\n\r\nexport default Sidebar\r\n"],"names":["Fragment"],"mappings":"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"}
1
+ {"version":3,"file":"Sidebar.js","sources":["../../../../../../src/legacy/components/layout/Sidebar/Sidebar.tsx"],"sourcesContent":["import React from 'react'\r\nimport SideNav, { type SideNavItem, type SideNavLabels } from '../../../../v1/components/layout/SideNav/SideNav'\r\n\r\n/*\r\n * Migrado para o V1: o menu lateral é o `SideNav` do V1 (normalmente dentro do\r\n * `AppShell`). Este ficheiro só mantém a API antiga, e os seus textos por\r\n * omissão, para as apps que ainda a usam.\r\n */\r\n\r\n/** @deprecated Legacy — usar `SideNavTheme` do V1. */\r\nexport type SidebarTheme = 'light' | 'dark' | 'system'\r\n\r\n/** @deprecated Legacy — usar `languages` do `SideNav` do V1. */\r\nexport interface SidebarLanguage {\r\n code: string\r\n label: string\r\n}\r\n\r\n/** @deprecated Legacy — usar `SideNavItem` do V1. */\r\nexport interface SidebarMenuItem {\r\n to: string\r\n icon: React.ComponentType<{ size?: number; className?: string }>\r\n label: string\r\n group?: string\r\n end?: boolean\r\n /** Contador opcional (ex: aprovações pendentes). */\r\n badge?: number\r\n /** Destino fora da aplicação: abre em separador novo. */\r\n external?: boolean\r\n}\r\n\r\n/** @deprecated Legacy — usar `SideNavProps` do V1. */\r\nexport interface SidebarProps {\r\n isOpen?: boolean\r\n setIsOpen?: (isOpen: boolean) => void\r\n menus: SidebarMenuItem[]\r\n groupLabels?: Record<string, string>\r\n appTitle?: string\r\n avatar?: React.ReactNode\r\n onLogout?: () => void\r\n logoutLabel?: string\r\n languages?: SidebarLanguage[]\r\n currentLang?: string\r\n onLanguageChange?: (code: string) => void\r\n theme?: SidebarTheme\r\n onThemeChange?: (theme: SidebarTheme) => void\r\n themeLabels?: { label?: string; light?: string; dark?: string; system?: string }\r\n footer?: (isExpanded: boolean) => React.ReactNode\r\n deployedAt?: string | number | Date\r\n deployedAtLabel?: string\r\n}\r\n\r\n/** Itens do menu antigo no formato do V1 (`badge` → `badges`). */\r\nexport const menuV1 = (menus: SidebarMenuItem[]): SideNavItem[] =>\r\n menus.map(({ badge, ...item }) => ({ ...item, end: item.end ?? item.to === '/', badges: badge ? [{ count: badge }] : undefined }))\r\n\r\n/** Os textos por omissão do menu antigo, para não mudarem nas apps que ainda o usam. */\r\nexport const labelsV1 = (\r\n p: Pick<SidebarProps, 'logoutLabel' | 'themeLabels' | 'deployedAtLabel'>,\r\n): Partial<SideNavLabels> => ({\r\n logout: p.logoutLabel ?? 'Logout',\r\n theme: p.themeLabels?.label ?? 'Theme',\r\n light: p.themeLabels?.light ?? 'Light',\r\n dark: p.themeLabels?.dark ?? 'Dark',\r\n system: p.themeLabels?.system ?? 'System',\r\n deployedAt: p.deployedAtLabel ?? 'Último deploy',\r\n})\r\n\r\n/** @deprecated Legacy — usar `SideNav` (ou `AppShell`) do V1. */\r\nconst Sidebar = ({\r\n isOpen = true,\r\n setIsOpen,\r\n menus,\r\n currentLang,\r\n logoutLabel,\r\n themeLabels,\r\n deployedAtLabel,\r\n ...rest\r\n}: SidebarProps) => (\r\n <SideNav\r\n {...rest}\r\n menu={menuV1(menus)}\r\n currentLanguage={currentLang}\r\n labels={labelsV1({ logoutLabel, themeLabels, deployedAtLabel })}\r\n open={isOpen}\r\n onOpenChange={setIsOpen ?? (() => {})}\r\n />\r\n)\r\n\r\nexport default Sidebar\r\n"],"names":[],"mappings":";;AAqDO,MAAM,SAAS,CAAC,UACrB,MAAM,IAAI,CAAC,EAAE,OAAO,GAAG,KAAA,OAAY,EAAE,GAAG,MAAM,KAAK,KAAK,OAAO,KAAK,OAAO,KAAK,QAAQ,QAAQ,CAAC,EAAE,OAAO,OAAO,IAAI,SAAY;AAG5H,MAAM,WAAW,CACtB,OAC4B;AAAA,EAC5B,QAAQ,EAAE,eAAe;AAAA,EACzB,OAAO,EAAE,aAAa,SAAS;AAAA,EAC/B,OAAO,EAAE,aAAa,SAAS;AAAA,EAC/B,MAAM,EAAE,aAAa,QAAQ;AAAA,EAC7B,QAAQ,EAAE,aAAa,UAAU;AAAA,EACjC,YAAY,EAAE,mBAAmB;AACnC;AAGA,MAAM,UAAU,CAAC;AAAA,EACf,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MACE;AAAA,EAAC;AAAA,EAAA;AAAA,IACE,GAAG;AAAA,IACJ,MAAM,OAAO,KAAK;AAAA,IAClB,iBAAiB;AAAA,IACjB,QAAQ,SAAS,EAAE,aAAa,aAAa,iBAAiB;AAAA,IAC9D,MAAM;AAAA,IACN,cAAc,cAAc,MAAM;AAAA,IAAC;AAAA,EAAA;AACrC;"}
@@ -1,13 +1,18 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
- import { useState, useRef, useEffect } from "react";
2
+ import { useState, useRef, useEffect, useMemo } from "react";
3
3
  const DEFAULT_LABELS = {
4
4
  title: "Columns",
5
5
  all: "All",
6
6
  none: "None",
7
7
  resetOrder: "Reset order",
8
+ reset: "Reset",
8
9
  moveUp: "Move up",
9
10
  moveDown: "Move down"
10
11
  };
12
+ const SEM_FIXAS = [];
13
+ function escondidasPorOmissao(columns, fixas) {
14
+ return columns.filter((c) => c.defaultHidden && !fixas.includes(c.key)).map((c) => c.key);
15
+ }
11
16
  const iconeBase = {
12
17
  viewBox: "0 0 24 24",
13
18
  fill: "none",
@@ -33,9 +38,12 @@ function ColumnPicker({
33
38
  order,
34
39
  onOrderChange,
35
40
  keepFirst = 1,
41
+ alwaysVisible = SEM_FIXAS,
42
+ onReset,
36
43
  labels
37
44
  }) {
38
45
  const L = { ...DEFAULT_LABELS, ...labels };
46
+ const textoRepor = labels?.reset ?? labels?.resetOrder ?? DEFAULT_LABELS.reset;
39
47
  const [aberto, setAberto] = useState(false);
40
48
  const caixa = useRef(null);
41
49
  useEffect(() => {
@@ -53,7 +61,10 @@ function ColumnPicker({
53
61
  document.removeEventListener("keydown", escape);
54
62
  };
55
63
  }, [aberto]);
64
+ const fixa = (key) => alwaysVisible.includes(key);
65
+ const escondida = (key) => hidden.has(key) && !fixa(key);
56
66
  const alternar = (key) => {
67
+ if (fixa(key)) return;
57
68
  const nova = new Set(hidden);
58
69
  if (nova.has(key)) nova.delete(key);
59
70
  else nova.add(key);
@@ -66,7 +77,14 @@ function ColumnPicker({
66
77
  [chaves[indice], chaves[destino]] = [chaves[destino], chaves[indice]];
67
78
  onOrderChange(chaves);
68
79
  };
69
- const visiveis = columns.length - hidden.size;
80
+ const visiveis = columns.filter((c) => !escondida(c.key)).length;
81
+ const omissao = escondidasPorOmissao(columns, alwaysVisible);
82
+ const visibilidadeMexida = columns.some((c) => escondida(c.key) !== omissao.includes(c.key));
83
+ const repor = () => {
84
+ if (onReset) return onReset();
85
+ onOrderChange([]);
86
+ onHiddenChange(new Set(omissao));
87
+ };
70
88
  return /* @__PURE__ */ jsxs("div", { className: "relative", ref: caixa, children: [
71
89
  /* @__PURE__ */ jsxs(
72
90
  "button",
@@ -101,20 +119,20 @@ function ColumnPicker({
101
119
  "button",
102
120
  {
103
121
  type: "button",
104
- onClick: () => onHiddenChange(new Set(columns.slice(keepFirst).map((c) => c.key))),
122
+ onClick: () => onHiddenChange(new Set(columns.slice(keepFirst).filter((c) => !fixa(c.key)).map((c) => c.key))),
105
123
  className: "appearance-none cursor-pointer bg-transparent border-0 px-2 py-1 text-xs font-medium text-slate-600 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-800",
106
124
  children: L.none
107
125
  }
108
126
  ),
109
- order.length > 0 && /* @__PURE__ */ jsxs(
127
+ (order.length > 0 || visibilidadeMexida) && /* @__PURE__ */ jsxs(
110
128
  "button",
111
129
  {
112
130
  type: "button",
113
- onClick: () => onOrderChange([]),
131
+ onClick: repor,
114
132
  className: "appearance-none cursor-pointer bg-transparent border-0 ml-auto inline-flex items-center gap-1 px-2 py-1 text-xs text-slate-500 dark:text-slate-400 hover:bg-slate-50 dark:hover:bg-slate-800",
115
133
  children: [
116
134
  /* @__PURE__ */ jsx(RotateCcw, { className: "h-3 w-3" }),
117
- L.resetOrder
135
+ textoRepor
118
136
  ]
119
137
  }
120
138
  )
@@ -125,12 +143,13 @@ function ColumnPicker({
125
143
  "input",
126
144
  {
127
145
  type: "checkbox",
128
- checked: !hidden.has(c.key),
146
+ checked: !escondida(c.key),
147
+ disabled: fixa(c.key),
129
148
  onChange: () => alternar(c.key),
130
- className: "h-4 w-4 border-slate-300 text-proef-blue rounded focus:ring-proef-blue"
149
+ className: "h-4 w-4 border-slate-300 text-proef-blue rounded focus:ring-proef-blue disabled:opacity-50 disabled:cursor-not-allowed"
131
150
  }
132
151
  ),
133
- /* @__PURE__ */ jsx("span", { className: `truncate ${hidden.has(c.key) ? "text-slate-400" : ""}`, children: c.label })
152
+ /* @__PURE__ */ jsx("span", { className: `truncate ${escondida(c.key) ? "text-slate-400" : ""}`, children: c.label })
134
153
  ] }),
135
154
  /* @__PURE__ */ jsx(
136
155
  "button",
@@ -171,9 +190,57 @@ function orderColumns(columns, order) {
171
190
  function applyColumnLayout(columns, order, hidden) {
172
191
  return orderColumns(columns, order).filter((c) => !hidden.has(c.key));
173
192
  }
193
+ function useColumnLayout(columns, { initial, onChange, alwaysVisible = SEM_FIXAS } = {}) {
194
+ const omissao = () => ({ hidden: escondidasPorOmissao(columns, alwaysVisible), order: [] });
195
+ const [layout, setLayoutState] = useState(() => initial ?? omissao());
196
+ const atual = useRef(layout);
197
+ atual.current = layout;
198
+ const avisar = useRef(onChange);
199
+ avisar.current = onChange;
200
+ const aplicado = useRef(initial !== void 0);
201
+ useEffect(() => {
202
+ if (!initial || aplicado.current) return;
203
+ aplicado.current = true;
204
+ atual.current = initial;
205
+ setLayoutState(initial);
206
+ }, [initial]);
207
+ const setLayout = (next) => {
208
+ const n = typeof next === "function" ? next(atual.current) : next;
209
+ const limpo = { hidden: n.hidden.filter((k) => !alwaysVisible.includes(k)), order: n.order };
210
+ aplicado.current = true;
211
+ atual.current = limpo;
212
+ setLayoutState(limpo);
213
+ avisar.current?.(limpo);
214
+ };
215
+ const reset = () => setLayout(omissao());
216
+ const chaveFixas = alwaysVisible.join("\0");
217
+ const hidden = useMemo(
218
+ () => new Set(layout.hidden.filter((k) => !alwaysVisible.includes(k))),
219
+ // eslint-disable-next-line react-hooks/exhaustive-deps
220
+ [layout.hidden, chaveFixas]
221
+ );
222
+ const visibleColumns = useMemo(() => applyColumnLayout(columns, layout.order, hidden), [columns, layout.order, hidden]);
223
+ const ordenadas = useMemo(() => orderColumns(columns, layout.order), [columns, layout.order]);
224
+ return {
225
+ visibleColumns,
226
+ layout,
227
+ setLayout,
228
+ reset,
229
+ pickerProps: {
230
+ columns: ordenadas,
231
+ hidden,
232
+ onHiddenChange: (h) => setLayout((l) => ({ ...l, hidden: [...h] })),
233
+ order: layout.order,
234
+ onOrderChange: (o) => setLayout((l) => ({ ...l, order: o })),
235
+ alwaysVisible,
236
+ onReset: reset
237
+ }
238
+ };
239
+ }
174
240
  export {
175
241
  applyColumnLayout,
176
242
  ColumnPicker as default,
177
- orderColumns
243
+ orderColumns,
244
+ useColumnLayout
178
245
  };
179
246
  //# sourceMappingURL=ColumnPicker.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ColumnPicker.js","sources":["../../../../../../src/legacy/components/molecules/ColumnPicker/ColumnPicker.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react'\r\n\r\n// ─── Tipos ──────────────────────────────────────────────────────────────────\r\n\r\n/** @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy. */\r\nexport interface ColumnPickerItem {\r\n key: string\r\n label: string\r\n}\r\n\r\n/** @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy. */\r\nexport interface ColumnPickerLabels {\r\n /** Texto do botão (escondido em ecrãs estreitos — a contagem fica sempre). */\r\n title: string\r\n all: string\r\n none: string\r\n resetOrder: string\r\n moveUp: string\r\n moveDown: string\r\n}\r\n\r\nconst DEFAULT_LABELS: ColumnPickerLabels = {\r\n title: 'Columns',\r\n all: 'All',\r\n none: 'None',\r\n resetOrder: 'Reset order',\r\n moveUp: 'Move up',\r\n moveDown: 'Move down',\r\n}\r\n\r\n// ─── Ícones (inline, sem dependências) ───────────────────────────────────────\r\n\r\nconst iconeBase = {\r\n viewBox: '0 0 24 24',\r\n fill: 'none',\r\n stroke: 'currentColor',\r\n strokeWidth: 2,\r\n strokeLinecap: 'round' as const,\r\n strokeLinejoin: 'round' as const,\r\n}\r\n\r\nconst Columns3 = ({ className }: { className?: string }) => (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" {...iconeBase} className={className} aria-hidden>\r\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\r\n <path d=\"M9 3v18M15 3v18\" />\r\n </svg>\r\n)\r\n\r\nconst ChevronUp = ({ className }: { className?: string }) => (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" {...iconeBase} className={className} aria-hidden>\r\n <path d=\"m18 15-6-6-6 6\" />\r\n </svg>\r\n)\r\n\r\nconst ChevronDown = ({ className }: { className?: string }) => (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" {...iconeBase} className={className} aria-hidden>\r\n <path d=\"m6 9 6 6 6-6\" />\r\n </svg>\r\n)\r\n\r\nconst RotateCcw = ({ className }: { className?: string }) => (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" {...iconeBase} className={className} aria-hidden>\r\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" />\r\n <path d=\"M3 3v5h5\" />\r\n </svg>\r\n)\r\n\r\n// ─── Componente ──────────────────────────────────────────────────────────────\r\n\r\ninterface Props {\r\n /** Colunas pela ordem em que estão a ser desenhadas (já reordenadas). */\r\n columns: ColumnPickerItem[]\r\n hidden: Set<string>\r\n onHiddenChange: (v: Set<string>) => void\r\n /** Ordem atual das chaves. Vazia = ordem natural das colunas. */\r\n order: string[]\r\n onOrderChange: (v: string[]) => void\r\n /**\r\n * Nº de colunas iniciais que \"Nenhuma\" nunca esconde — uma tabela sem colunas\r\n * nenhumas não é utilizável. Default 1.\r\n */\r\n keepFirst?: number\r\n labels?: Partial<ColumnPickerLabels>\r\n}\r\n\r\n/**\r\n * Escolha e ordenação das colunas de uma tabela.\r\n *\r\n * Vive fora do `DataTable` de propósito: a tabela recebe as colunas já filtradas e\r\n * ordenadas e limita-se a desenhar o que lhe é dado. Quem decide (e quem guarda a\r\n * escolha, se quiser) é o ecrã.\r\n *\r\n * As colunas escondidas continuam listadas, para poderem ser reordenadas antes de\r\n * voltarem a aparecer.\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport default function ColumnPicker({\r\n columns,\r\n hidden,\r\n onHiddenChange,\r\n order,\r\n onOrderChange,\r\n keepFirst = 1,\r\n labels,\r\n}: Props) {\r\n const L = { ...DEFAULT_LABELS, ...labels }\r\n const [aberto, setAberto] = useState(false)\r\n const caixa = useRef<HTMLDivElement | null>(null)\r\n\r\n useEffect(() => {\r\n if (!aberto) return\r\n const fora = (e: MouseEvent) => {\r\n if (caixa.current && !caixa.current.contains(e.target as Node)) setAberto(false)\r\n }\r\n const escape = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') setAberto(false)\r\n }\r\n document.addEventListener('mousedown', fora)\r\n document.addEventListener('keydown', escape)\r\n return () => {\r\n document.removeEventListener('mousedown', fora)\r\n document.removeEventListener('keydown', escape)\r\n }\r\n }, [aberto])\r\n\r\n const alternar = (key: string) => {\r\n const nova = new Set(hidden)\r\n if (nova.has(key)) nova.delete(key)\r\n else nova.add(key)\r\n onHiddenChange(nova)\r\n }\r\n\r\n /**\r\n * Move uma coluna uma posição. Escreve a lista inteira de chaves e não só a troca,\r\n * para a ordem guardada ficar completa mesmo antes de o utilizador ter mexido em tudo.\r\n */\r\n const mover = (indice: number, passo: number) => {\r\n const destino = indice + passo\r\n if (destino < 0 || destino >= columns.length) return\r\n const chaves = columns.map((c) => c.key)\r\n ;[chaves[indice], chaves[destino]] = [chaves[destino]!, chaves[indice]!]\r\n onOrderChange(chaves)\r\n }\r\n\r\n const visiveis = columns.length - hidden.size\r\n\r\n return (\r\n <div className=\"relative\" ref={caixa}>\r\n <button\r\n type=\"button\"\r\n onClick={() => setAberto((v) => !v)}\r\n aria-expanded={aberto}\r\n className=\"appearance-none cursor-pointer bg-white inline-flex items-center gap-2 h-8 rounded-lg border border-slate-300 px-3 text-xs font-medium text-slate-700 transition hover:bg-slate-50 dark:bg-slate-800 dark:border-slate-600 dark:text-slate-200 dark:hover:bg-slate-700\"\r\n >\r\n <Columns3 className=\"h-4 w-4\" />\r\n <span className=\"hidden sm:inline\">{L.title}</span>\r\n <span className=\"tabular-nums text-xs text-slate-400\">\r\n {visiveis}/{columns.length}\r\n </span>\r\n </button>\r\n\r\n {aberto && (\r\n <div className=\"absolute right-0 z-30 mt-1 w-72 overflow-hidden rounded-lg border border-slate-200 bg-white shadow-lg dark:bg-slate-900 dark:border-slate-700\">\r\n <div className=\"flex items-center gap-1 border-b border-slate-100 dark:border-slate-800 px-2 py-1.5\">\r\n <button\r\n type=\"button\"\r\n onClick={() => onHiddenChange(new Set())}\r\n className=\"appearance-none cursor-pointer bg-transparent border-0 px-2 py-1 text-xs font-medium text-proef-blue dark:text-sky-300 hover:bg-slate-50 dark:hover:bg-slate-800\"\r\n >\r\n {L.all}\r\n </button>\r\n <button\r\n type=\"button\"\r\n onClick={() => onHiddenChange(new Set(columns.slice(keepFirst).map((c) => c.key)))}\r\n className=\"appearance-none cursor-pointer bg-transparent border-0 px-2 py-1 text-xs font-medium text-slate-600 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-800\"\r\n >\r\n {L.none}\r\n </button>\r\n {order.length > 0 && (\r\n <button\r\n type=\"button\"\r\n onClick={() => onOrderChange([])}\r\n className=\"appearance-none cursor-pointer bg-transparent border-0 ml-auto inline-flex items-center gap-1 px-2 py-1 text-xs text-slate-500 dark:text-slate-400 hover:bg-slate-50 dark:hover:bg-slate-800\"\r\n >\r\n <RotateCcw className=\"h-3 w-3\" />\r\n {L.resetOrder}\r\n </button>\r\n )}\r\n </div>\r\n\r\n <ul className=\"max-h-80 overflow-y-auto py-1 list-none m-0 pl-0\">\r\n {columns.map((c, i) => (\r\n <li key={c.key} className=\"flex items-center gap-2 px-2 py-1 hover:bg-slate-50 dark:hover:bg-slate-800\">\r\n <label className=\"flex min-w-0 flex-1 cursor-pointer items-center gap-2 text-sm text-slate-700 dark:text-slate-200\">\r\n <input\r\n type=\"checkbox\"\r\n checked={!hidden.has(c.key)}\r\n onChange={() => alternar(c.key)}\r\n className=\"h-4 w-4 border-slate-300 text-proef-blue rounded focus:ring-proef-blue\"\r\n />\r\n <span className={`truncate ${hidden.has(c.key) ? 'text-slate-400' : ''}`}>{c.label}</span>\r\n </label>\r\n <button\r\n type=\"button\"\r\n onClick={() => mover(i, -1)}\r\n disabled={i === 0}\r\n aria-label={L.moveUp}\r\n title={L.moveUp}\r\n className=\"appearance-none cursor-pointer bg-transparent border-0 p-0.5 text-slate-400 hover:text-proef-navy dark:hover:text-white disabled:opacity-25 disabled:cursor-not-allowed\"\r\n >\r\n <ChevronUp className=\"h-3.5 w-3.5\" />\r\n </button>\r\n <button\r\n type=\"button\"\r\n onClick={() => mover(i, 1)}\r\n disabled={i === columns.length - 1}\r\n aria-label={L.moveDown}\r\n title={L.moveDown}\r\n className=\"appearance-none cursor-pointer bg-transparent border-0 p-0.5 text-slate-400 hover:text-proef-navy dark:hover:text-white disabled:opacity-25 disabled:cursor-not-allowed\"\r\n >\r\n <ChevronDown className=\"h-3.5 w-3.5\" />\r\n </button>\r\n </li>\r\n ))}\r\n </ul>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n\r\n/**\r\n * Reordena as colunas por `order`. Chaves fora de `order` ficam no fim, pela ordem natural —\r\n * assim uma ordem guardada antes de a tabela ganhar colunas novas continua a servir, em vez\r\n * de as fazer desaparecer.\r\n *\r\n * É esta lista (com as escondidas incluídas) que o `ColumnPicker` recebe: uma coluna que\r\n * deixasse de ser listada por estar escondida não tinha como voltar.\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport function orderColumns<C extends { key: string }>(columns: C[], order: string[]): C[] {\r\n if (order.length === 0) return columns\r\n const posicao = (c: C, i: number) => {\r\n const p = order.indexOf(c.key)\r\n return p === -1 ? order.length + i : p\r\n }\r\n return columns\r\n .map((c, i) => ({ c, p: posicao(c, i) }))\r\n .sort((a, b) => a.p - b.p)\r\n .map(({ c }) => c)\r\n}\r\n\r\n/**\r\n * `orderColumns` + remoção das escondidas. É o que se passa à tabela.\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport function applyColumnLayout<C extends { key: string }>(\r\n columns: C[],\r\n order: string[],\r\n hidden: Set<string>\r\n): C[] {\r\n return orderColumns(columns, order).filter((c) => !hidden.has(c.key))\r\n}\r\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ColumnPicker.js","sources":["../../../../../../src/legacy/components/molecules/ColumnPicker/ColumnPicker.tsx"],"sourcesContent":["import React, { useEffect, useMemo, useRef, useState } from 'react'\r\nimport type { DataTableColumn } from '../DataTable/DataTable'\r\n\r\n// ─── Tipos ──────────────────────────────────────────────────────────────────\r\n\r\n/** @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy. */\r\nexport interface ColumnPickerItem {\r\n key: string\r\n label: string\r\n /** Escondida por omissão — é assim que o \"Repor\" a deixa. */\r\n defaultHidden?: boolean\r\n}\r\n\r\n/** @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy. */\r\nexport interface ColumnPickerLabels {\r\n /** Texto do botão (escondido em ecrãs estreitos — a contagem fica sempre). */\r\n title: string\r\n all: string\r\n none: string\r\n /** @deprecated O botão repõe ordem e visibilidade — usar `reset`. Continua a servir de texto quando `reset` não vem. */\r\n resetOrder: string\r\n /** Texto do botão que repõe ordem e colunas visíveis por omissão. */\r\n reset?: string\r\n moveUp: string\r\n moveDown: string\r\n}\r\n\r\nconst DEFAULT_LABELS: ColumnPickerLabels = {\r\n title: 'Columns',\r\n all: 'All',\r\n none: 'None',\r\n resetOrder: 'Reset order',\r\n reset: 'Reset',\r\n moveUp: 'Move up',\r\n moveDown: 'Move down',\r\n}\r\n\r\n/** Layout de colunas guardável (ex.: numa API): chaves escondidas e ordem (vazia = ordem natural). */\r\nexport interface ColumnLayout {\r\n hidden: string[]\r\n order: string[]\r\n}\r\n\r\n/** Identidade estável para \"sem colunas fixas\". */\r\nconst SEM_FIXAS: string[] = []\r\n\r\n/** Escondidas por omissão: as `defaultHidden`, menos as que têm de estar sempre à vista. */\r\nfunction escondidasPorOmissao(columns: ColumnPickerItem[], fixas: string[]): string[] {\r\n return columns.filter((c) => c.defaultHidden && !fixas.includes(c.key)).map((c) => c.key)\r\n}\r\n\r\n// ─── Ícones (inline, sem dependências) ───────────────────────────────────────\r\n\r\nconst iconeBase = {\r\n viewBox: '0 0 24 24',\r\n fill: 'none',\r\n stroke: 'currentColor',\r\n strokeWidth: 2,\r\n strokeLinecap: 'round' as const,\r\n strokeLinejoin: 'round' as const,\r\n}\r\n\r\nconst Columns3 = ({ className }: { className?: string }) => (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" {...iconeBase} className={className} aria-hidden>\r\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\r\n <path d=\"M9 3v18M15 3v18\" />\r\n </svg>\r\n)\r\n\r\nconst ChevronUp = ({ className }: { className?: string }) => (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" {...iconeBase} className={className} aria-hidden>\r\n <path d=\"m18 15-6-6-6 6\" />\r\n </svg>\r\n)\r\n\r\nconst ChevronDown = ({ className }: { className?: string }) => (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" {...iconeBase} className={className} aria-hidden>\r\n <path d=\"m6 9 6 6 6-6\" />\r\n </svg>\r\n)\r\n\r\nconst RotateCcw = ({ className }: { className?: string }) => (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" {...iconeBase} className={className} aria-hidden>\r\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" />\r\n <path d=\"M3 3v5h5\" />\r\n </svg>\r\n)\r\n\r\n// ─── Componente ──────────────────────────────────────────────────────────────\r\n\r\n/** @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy. */\r\nexport interface ColumnPickerProps {\r\n /** Colunas pela ordem em que estão a ser desenhadas (já reordenadas). */\r\n columns: ColumnPickerItem[]\r\n hidden: Set<string>\r\n onHiddenChange: (v: Set<string>) => void\r\n /** Ordem atual das chaves. Vazia = ordem natural das colunas. */\r\n order: string[]\r\n onOrderChange: (v: string[]) => void\r\n /**\r\n * Nº de colunas iniciais que \"Nenhuma\" nunca esconde — uma tabela sem colunas\r\n * nenhumas não é utilizável. Default 1.\r\n */\r\n keepFirst?: number\r\n /** Chaves que ficam sempre à vista: a caixa aparece marcada e desativada, e \"Nenhuma\" não as esconde. */\r\n alwaysVisible?: string[]\r\n /**\r\n * Substitui o \"Repor\". Por omissão chama `onOrderChange([])` e `onHiddenChange` com as `defaultHidden`;\r\n * o `useColumnLayout` passa aqui o seu `reset`, para repor as duas coisas num só aviso.\r\n */\r\n onReset?: () => void\r\n labels?: Partial<ColumnPickerLabels>\r\n}\r\n\r\n/**\r\n * Escolha e ordenação das colunas de uma tabela.\r\n *\r\n * Vive fora do `DataTable` de propósito: a tabela recebe as colunas já filtradas e\r\n * ordenadas e limita-se a desenhar o que lhe é dado. Quem decide (e quem guarda a\r\n * escolha, se quiser) é o ecrã.\r\n *\r\n * As colunas escondidas continuam listadas, para poderem ser reordenadas antes de\r\n * voltarem a aparecer.\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport default function ColumnPicker({\r\n columns,\r\n hidden,\r\n onHiddenChange,\r\n order,\r\n onOrderChange,\r\n keepFirst = 1,\r\n alwaysVisible = SEM_FIXAS,\r\n onReset,\r\n labels,\r\n}: ColumnPickerProps) {\r\n const L = { ...DEFAULT_LABELS, ...labels }\r\n const textoRepor = labels?.reset ?? labels?.resetOrder ?? DEFAULT_LABELS.reset\r\n const [aberto, setAberto] = useState(false)\r\n const caixa = useRef<HTMLDivElement | null>(null)\r\n\r\n useEffect(() => {\r\n if (!aberto) return\r\n const fora = (e: MouseEvent) => {\r\n if (caixa.current && !caixa.current.contains(e.target as Node)) setAberto(false)\r\n }\r\n const escape = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') setAberto(false)\r\n }\r\n document.addEventListener('mousedown', fora)\r\n document.addEventListener('keydown', escape)\r\n return () => {\r\n document.removeEventListener('mousedown', fora)\r\n document.removeEventListener('keydown', escape)\r\n }\r\n }, [aberto])\r\n\r\n const fixa = (key: string) => alwaysVisible.includes(key)\r\n const escondida = (key: string) => hidden.has(key) && !fixa(key)\r\n\r\n const alternar = (key: string) => {\r\n if (fixa(key)) return\r\n const nova = new Set(hidden)\r\n if (nova.has(key)) nova.delete(key)\r\n else nova.add(key)\r\n onHiddenChange(nova)\r\n }\r\n\r\n /**\r\n * Move uma coluna uma posição. Escreve a lista inteira de chaves e não só a troca,\r\n * para a ordem guardada ficar completa mesmo antes de o utilizador ter mexido em tudo.\r\n */\r\n const mover = (indice: number, passo: number) => {\r\n const destino = indice + passo\r\n if (destino < 0 || destino >= columns.length) return\r\n const chaves = columns.map((c) => c.key)\r\n ;[chaves[indice], chaves[destino]] = [chaves[destino]!, chaves[indice]!]\r\n onOrderChange(chaves)\r\n }\r\n\r\n // Conta pelas colunas (e não por `hidden.size`): chaves guardadas de colunas que já não existem não contam.\r\n const visiveis = columns.filter((c) => !escondida(c.key)).length\r\n\r\n const omissao = escondidasPorOmissao(columns, alwaysVisible)\r\n const visibilidadeMexida = columns.some((c) => escondida(c.key) !== omissao.includes(c.key))\r\n const repor = () => {\r\n if (onReset) return onReset()\r\n onOrderChange([])\r\n onHiddenChange(new Set(omissao))\r\n }\r\n\r\n return (\r\n <div className=\"relative\" ref={caixa}>\r\n <button\r\n type=\"button\"\r\n onClick={() => setAberto((v) => !v)}\r\n aria-expanded={aberto}\r\n className=\"appearance-none cursor-pointer bg-white inline-flex items-center gap-2 h-8 rounded-lg border border-slate-300 px-3 text-xs font-medium text-slate-700 transition hover:bg-slate-50 dark:bg-slate-800 dark:border-slate-600 dark:text-slate-200 dark:hover:bg-slate-700\"\r\n >\r\n <Columns3 className=\"h-4 w-4\" />\r\n <span className=\"hidden sm:inline\">{L.title}</span>\r\n <span className=\"tabular-nums text-xs text-slate-400\">\r\n {visiveis}/{columns.length}\r\n </span>\r\n </button>\r\n\r\n {aberto && (\r\n <div className=\"absolute right-0 z-30 mt-1 w-72 overflow-hidden rounded-lg border border-slate-200 bg-white shadow-lg dark:bg-slate-900 dark:border-slate-700\">\r\n <div className=\"flex items-center gap-1 border-b border-slate-100 dark:border-slate-800 px-2 py-1.5\">\r\n <button\r\n type=\"button\"\r\n onClick={() => onHiddenChange(new Set())}\r\n className=\"appearance-none cursor-pointer bg-transparent border-0 px-2 py-1 text-xs font-medium text-proef-blue dark:text-sky-300 hover:bg-slate-50 dark:hover:bg-slate-800\"\r\n >\r\n {L.all}\r\n </button>\r\n <button\r\n type=\"button\"\r\n onClick={() => onHiddenChange(new Set(columns.slice(keepFirst).filter((c) => !fixa(c.key)).map((c) => c.key)))}\r\n className=\"appearance-none cursor-pointer bg-transparent border-0 px-2 py-1 text-xs font-medium text-slate-600 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-800\"\r\n >\r\n {L.none}\r\n </button>\r\n {(order.length > 0 || visibilidadeMexida) && (\r\n <button\r\n type=\"button\"\r\n onClick={repor}\r\n className=\"appearance-none cursor-pointer bg-transparent border-0 ml-auto inline-flex items-center gap-1 px-2 py-1 text-xs text-slate-500 dark:text-slate-400 hover:bg-slate-50 dark:hover:bg-slate-800\"\r\n >\r\n <RotateCcw className=\"h-3 w-3\" />\r\n {textoRepor}\r\n </button>\r\n )}\r\n </div>\r\n\r\n <ul className=\"max-h-80 overflow-y-auto py-1 list-none m-0 pl-0\">\r\n {columns.map((c, i) => (\r\n <li key={c.key} className=\"flex items-center gap-2 px-2 py-1 hover:bg-slate-50 dark:hover:bg-slate-800\">\r\n <label className=\"flex min-w-0 flex-1 cursor-pointer items-center gap-2 text-sm text-slate-700 dark:text-slate-200\">\r\n <input\r\n type=\"checkbox\"\r\n checked={!escondida(c.key)}\r\n disabled={fixa(c.key)}\r\n onChange={() => alternar(c.key)}\r\n className=\"h-4 w-4 border-slate-300 text-proef-blue rounded focus:ring-proef-blue disabled:opacity-50 disabled:cursor-not-allowed\"\r\n />\r\n <span className={`truncate ${escondida(c.key) ? 'text-slate-400' : ''}`}>{c.label}</span>\r\n </label>\r\n <button\r\n type=\"button\"\r\n onClick={() => mover(i, -1)}\r\n disabled={i === 0}\r\n aria-label={L.moveUp}\r\n title={L.moveUp}\r\n className=\"appearance-none cursor-pointer bg-transparent border-0 p-0.5 text-slate-400 hover:text-proef-navy dark:hover:text-white disabled:opacity-25 disabled:cursor-not-allowed\"\r\n >\r\n <ChevronUp className=\"h-3.5 w-3.5\" />\r\n </button>\r\n <button\r\n type=\"button\"\r\n onClick={() => mover(i, 1)}\r\n disabled={i === columns.length - 1}\r\n aria-label={L.moveDown}\r\n title={L.moveDown}\r\n className=\"appearance-none cursor-pointer bg-transparent border-0 p-0.5 text-slate-400 hover:text-proef-navy dark:hover:text-white disabled:opacity-25 disabled:cursor-not-allowed\"\r\n >\r\n <ChevronDown className=\"h-3.5 w-3.5\" />\r\n </button>\r\n </li>\r\n ))}\r\n </ul>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n\r\n/**\r\n * Reordena as colunas por `order`. Chaves fora de `order` ficam no fim, pela ordem natural —\r\n * assim uma ordem guardada antes de a tabela ganhar colunas novas continua a servir, em vez\r\n * de as fazer desaparecer.\r\n *\r\n * É esta lista (com as escondidas incluídas) que o `ColumnPicker` recebe: uma coluna que\r\n * deixasse de ser listada por estar escondida não tinha como voltar.\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport function orderColumns<C extends { key: string }>(columns: C[], order: string[]): C[] {\r\n if (order.length === 0) return columns\r\n const posicao = (c: C, i: number) => {\r\n const p = order.indexOf(c.key)\r\n return p === -1 ? order.length + i : p\r\n }\r\n return columns\r\n .map((c, i) => ({ c, p: posicao(c, i) }))\r\n .sort((a, b) => a.p - b.p)\r\n .map(({ c }) => c)\r\n}\r\n\r\n/**\r\n * `orderColumns` + remoção das escondidas. É o que se passa à tabela.\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport function applyColumnLayout<C extends { key: string }>(\r\n columns: C[],\r\n order: string[],\r\n hidden: Set<string>\r\n): C[] {\r\n return orderColumns(columns, order).filter((c) => !hidden.has(c.key))\r\n}\r\n\r\n/** @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy. */\r\nexport interface UseColumnLayoutOptions {\r\n /**\r\n * Layout guardado (ex.: vindo de uma API). Pode chegar depois de montar: aplica-se quando deixa de ser\r\n * `undefined` — a não ser que a pessoa já tenha mexido entretanto. Sem layout guardado não se passa\r\n * (ficam as `defaultHidden`).\r\n */\r\n initial?: ColumnLayout\r\n /** Chamado a cada mudança feita pela pessoa (inclui o \"Repor\"). É aqui que a app guarda. */\r\n onChange?: (layout: ColumnLayout) => void\r\n /** Chaves que nunca se escondem (ver `ColumnPicker.alwaysVisible`). */\r\n alwaysVisible?: string[]\r\n}\r\n\r\n/** @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy. */\r\nexport interface UseColumnLayoutResult<C extends ColumnPickerItem> {\r\n /** Colunas a passar à tabela: ordenadas e sem as escondidas. */\r\n visibleColumns: C[]\r\n layout: ColumnLayout\r\n /** Muda o layout (valor ou função do anterior) e avisa `onChange`. */\r\n setLayout: (next: ColumnLayout | ((prev: ColumnLayout) => ColumnLayout)) => void\r\n /** Volta à ordem natural com as `defaultHidden` escondidas, e avisa `onChange`. */\r\n reset: () => void\r\n /** Props prontas para `<ColumnPicker {...pickerProps} />`. */\r\n pickerProps: Pick<ColumnPickerProps, 'hidden' | 'onHiddenChange' | 'order' | 'onOrderChange' | 'alwaysVisible' | 'onReset'> & {\r\n columns: C[]\r\n }\r\n}\r\n\r\n/**\r\n * Estado do layout de colunas (visibilidade + ordem) para ligar ao `ColumnPicker` e à tabela.\r\n *\r\n * Não guarda nada: quem persiste (sessão, API do servidor…) é a app, com `initial` + `onChange`. Arranca com\r\n * as `defaultHidden` escondidas e as `alwaysVisible` nunca saem.\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport function useColumnLayout<T, C extends ColumnPickerItem = DataTableColumn<T>>(\r\n columns: C[],\r\n { initial, onChange, alwaysVisible = SEM_FIXAS }: UseColumnLayoutOptions = {}\r\n): UseColumnLayoutResult<C> {\r\n const omissao = (): ColumnLayout => ({ hidden: escondidasPorOmissao(columns, alwaysVisible), order: [] })\r\n const [layout, setLayoutState] = useState<ColumnLayout>(() => initial ?? omissao())\r\n\r\n // O mais recente, para mudanças seguidas no mesmo evento se encadearem (sem efeitos dentro do updater).\r\n const atual = useRef(layout)\r\n atual.current = layout\r\n const avisar = useRef(onChange)\r\n avisar.current = onChange\r\n\r\n // `initial` assíncrono: aplica-se uma vez, quando chega — sem avisar `onChange` (não foi a pessoa que mudou).\r\n const aplicado = useRef(initial !== undefined)\r\n useEffect(() => {\r\n if (!initial || aplicado.current) return\r\n aplicado.current = true\r\n atual.current = initial\r\n setLayoutState(initial)\r\n }, [initial])\r\n\r\n const setLayout = (next: ColumnLayout | ((prev: ColumnLayout) => ColumnLayout)) => {\r\n const n = typeof next === 'function' ? next(atual.current) : next\r\n const limpo = { hidden: n.hidden.filter((k) => !alwaysVisible.includes(k)), order: n.order }\r\n aplicado.current = true\r\n atual.current = limpo\r\n setLayoutState(limpo)\r\n avisar.current?.(limpo)\r\n }\r\n const reset = () => setLayout(omissao())\r\n\r\n const chaveFixas = alwaysVisible.join('\\u0000')\r\n const hidden = useMemo(\r\n () => new Set(layout.hidden.filter((k) => !alwaysVisible.includes(k))),\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n [layout.hidden, chaveFixas]\r\n )\r\n const visibleColumns = useMemo(() => applyColumnLayout(columns, layout.order, hidden), [columns, layout.order, hidden])\r\n const ordenadas = useMemo(() => orderColumns(columns, layout.order), [columns, layout.order])\r\n\r\n return {\r\n visibleColumns,\r\n layout,\r\n setLayout,\r\n reset,\r\n pickerProps: {\r\n columns: ordenadas,\r\n hidden,\r\n onHiddenChange: (h) => setLayout((l) => ({ ...l, hidden: [...h] })),\r\n order: layout.order,\r\n onOrderChange: (o) => setLayout((l) => ({ ...l, order: o })),\r\n alwaysVisible,\r\n onReset: reset,\r\n },\r\n }\r\n}\r\n"],"names":[],"mappings":"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"}