@ifto/mantine-kit 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (298) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +471 -2
  3. package/dist/component/atom/AppMain/App.module.js +7 -0
  4. package/dist/component/atom/AppMain/App.module.js.map +1 -0
  5. package/dist/component/atom/AppMain/AppMain.d.ts +7 -0
  6. package/dist/component/atom/AppMain/AppMain.js +14 -0
  7. package/dist/component/atom/AppMain/AppMain.js.map +1 -0
  8. package/dist/component/atom/CancelEditButton/CancelEditButton.d.ts +6 -0
  9. package/dist/component/atom/CancelEditButton/CancelEditButton.js +24 -0
  10. package/dist/component/atom/CancelEditButton/CancelEditButton.js.map +1 -0
  11. package/dist/component/atom/ConfirmEditButton/ConfirmEditButton.d.ts +13 -0
  12. package/dist/component/atom/ConfirmEditButton/ConfirmEditButton.js +30 -0
  13. package/dist/component/atom/ConfirmEditButton/ConfirmEditButton.js.map +1 -0
  14. package/dist/component/atom/DateField/DateField.d.ts +7 -0
  15. package/dist/component/atom/DateField/DateField.js +21 -0
  16. package/dist/component/atom/DateField/DateField.js.map +1 -0
  17. package/dist/component/atom/EditValueButton/EditValueButton.d.ts +6 -0
  18. package/dist/component/atom/EditValueButton/EditValueButton.js +24 -0
  19. package/dist/component/atom/EditValueButton/EditValueButton.js.map +1 -0
  20. package/dist/component/atom/ErrorAlert/ErrorAlert.d.ts +8 -0
  21. package/dist/component/atom/ErrorAlert/ErrorAlert.js +21 -0
  22. package/dist/component/atom/ErrorAlert/ErrorAlert.js.map +1 -0
  23. package/dist/component/atom/Surface/Surface.d.ts +20 -0
  24. package/dist/component/atom/Surface/Surface.js +15 -0
  25. package/dist/component/atom/Surface/Surface.js.map +1 -0
  26. package/dist/component/molecule/Breadcrumb/Breadcrumb.d.ts +12 -0
  27. package/dist/component/molecule/Breadcrumb/Breadcrumb.js +38 -0
  28. package/dist/component/molecule/Breadcrumb/Breadcrumb.js.map +1 -0
  29. package/dist/component/molecule/ExportMenuButton/ExportMenuButton.d.ts +25 -0
  30. package/dist/component/molecule/ExportMenuButton/ExportMenuButton.js +49 -0
  31. package/dist/component/molecule/ExportMenuButton/ExportMenuButton.js.map +1 -0
  32. package/dist/component/molecule/PaperCard/PaperCard.d.ts +7 -0
  33. package/dist/component/molecule/PaperCard/PaperCard.js +17 -0
  34. package/dist/component/molecule/PaperCard/PaperCard.js.map +1 -0
  35. package/dist/component/molecule/PrintSection/PrintSection.d.ts +14 -0
  36. package/dist/component/molecule/PrintSection/PrintSection.js +29 -0
  37. package/dist/component/molecule/PrintSection/PrintSection.js.map +1 -0
  38. package/dist/component/molecule/SelectField/SelectField.d.ts +32 -0
  39. package/dist/component/molecule/SelectField/SelectField.js +38 -0
  40. package/dist/component/molecule/SelectField/SelectField.js.map +1 -0
  41. package/dist/component/molecule/StatsCard/Stats.module.js +15 -0
  42. package/dist/component/molecule/StatsCard/Stats.module.js.map +1 -0
  43. package/dist/component/molecule/StatsCard/StatsCard.d.ts +18 -0
  44. package/dist/component/molecule/StatsCard/StatsCard.js +60 -0
  45. package/dist/component/molecule/StatsCard/StatsCard.js.map +1 -0
  46. package/dist/component/organism/DataForm/DataForm.d.ts +26 -0
  47. package/dist/component/organism/DataForm/DataForm.js +83 -0
  48. package/dist/component/organism/DataForm/DataForm.js.map +1 -0
  49. package/dist/component/organism/DataTabList/DataTabList.d.ts +24 -0
  50. package/dist/component/organism/DataTabList/DataTabList.js +37 -0
  51. package/dist/component/organism/DataTabList/DataTabList.js.map +1 -0
  52. package/dist/component/organism/DataTabList/DataTabList.module.js +13 -0
  53. package/dist/component/organism/DataTabList/DataTabList.module.js.map +1 -0
  54. package/dist/component/organism/EChart/EChart.d.ts +47 -0
  55. package/dist/component/organism/EChart/EChart.js +37 -0
  56. package/dist/component/organism/EChart/EChart.js.map +1 -0
  57. package/dist/component/organism/EChart/buildEChartOption.d.ts +40 -0
  58. package/dist/component/organism/EChart/buildEChartOption.js +57 -0
  59. package/dist/component/organism/EChart/buildEChartOption.js.map +1 -0
  60. package/dist/component/organism/EChart/chart/BarChart.d.ts +22 -0
  61. package/dist/component/organism/EChart/chart/BarChart.js +34 -0
  62. package/dist/component/organism/EChart/chart/BarChart.js.map +1 -0
  63. package/dist/component/organism/EChart/chart/CartesianChart.d.ts +48 -0
  64. package/dist/component/organism/EChart/chart/CartesianChart.js +63 -0
  65. package/dist/component/organism/EChart/chart/CartesianChart.js.map +1 -0
  66. package/dist/component/organism/EChart/chart/ChartHeader.d.ts +36 -0
  67. package/dist/component/organism/EChart/chart/ChartHeader.js +105 -0
  68. package/dist/component/organism/EChart/chart/ChartHeader.js.map +1 -0
  69. package/dist/component/organism/EChart/chart/ChartSeries.d.ts +50 -0
  70. package/dist/component/organism/EChart/chart/ChartSeries.js +23 -0
  71. package/dist/component/organism/EChart/chart/ChartSeries.js.map +1 -0
  72. package/dist/component/organism/EChart/chart/ChartTexts.d.ts +12 -0
  73. package/dist/component/organism/EChart/chart/ChartTexts.js +21 -0
  74. package/dist/component/organism/EChart/chart/ChartTexts.js.map +1 -0
  75. package/dist/component/organism/EChart/chart/ChartType.d.ts +50 -0
  76. package/dist/component/organism/EChart/chart/ChartType.js +1 -0
  77. package/dist/component/organism/EChart/chart/ChartTypeId.d.ts +2 -0
  78. package/dist/component/organism/EChart/chart/ChartTypeId.js +1 -0
  79. package/dist/component/organism/EChart/chart/ChartTypes.d.ts +15 -0
  80. package/dist/component/organism/EChart/chart/ChartTypes.js +24 -0
  81. package/dist/component/organism/EChart/chart/ChartTypes.js.map +1 -0
  82. package/dist/component/organism/EChart/chart/DonutChart.d.ts +32 -0
  83. package/dist/component/organism/EChart/chart/DonutChart.js +111 -0
  84. package/dist/component/organism/EChart/chart/DonutChart.js.map +1 -0
  85. package/dist/component/organism/EChart/chart/LineChart.d.ts +11 -0
  86. package/dist/component/organism/EChart/chart/LineChart.js +20 -0
  87. package/dist/component/organism/EChart/chart/LineChart.js.map +1 -0
  88. package/dist/component/organism/EChart/chart/StackedBarChart.d.ts +15 -0
  89. package/dist/component/organism/EChart/chart/StackedBarChart.js +30 -0
  90. package/dist/component/organism/EChart/chart/StackedBarChart.js.map +1 -0
  91. package/dist/component/organism/EChart/chart/UnitPanels.d.ts +63 -0
  92. package/dist/component/organism/EChart/chart/UnitPanels.js +127 -0
  93. package/dist/component/organism/EChart/chart/UnitPanels.js.map +1 -0
  94. package/dist/component/organism/EChart/echartDefaults.d.ts +32 -0
  95. package/dist/component/organism/EChart/echartDefaults.js +47 -0
  96. package/dist/component/organism/EChart/echartDefaults.js.map +1 -0
  97. package/dist/component/organism/EChart/useEChart.d.ts +35 -0
  98. package/dist/component/organism/EChart/useEChart.js +112 -0
  99. package/dist/component/organism/EChart/useEChart.js.map +1 -0
  100. package/dist/component/organism/Navbar/NavItem.d.ts +16 -0
  101. package/dist/component/organism/Navbar/NavItem.js +1 -0
  102. package/dist/component/organism/Navbar/Navbar.d.ts +20 -0
  103. package/dist/component/organism/Navbar/Navbar.js +64 -0
  104. package/dist/component/organism/Navbar/Navbar.js.map +1 -0
  105. package/dist/component/organism/Navbar/Navbar.module.js +19 -0
  106. package/dist/component/organism/Navbar/Navbar.module.js.map +1 -0
  107. package/dist/component/organism/PageHeader/PageHeader.d.ts +14 -0
  108. package/dist/component/organism/PageHeader/PageHeader.js +55 -0
  109. package/dist/component/organism/PageHeader/PageHeader.js.map +1 -0
  110. package/dist/component/organism/StatsGrid/StatsGrid.d.ts +12 -0
  111. package/dist/component/organism/StatsGrid/StatsGrid.js +46 -0
  112. package/dist/component/organism/StatsGrid/StatsGrid.js.map +1 -0
  113. package/dist/component/organism/StatsGrid/StatsGrid.module.js +17 -0
  114. package/dist/component/organism/StatsGrid/StatsGrid.module.js.map +1 -0
  115. package/dist/component/organism/Table/RowActions.d.ts +23 -0
  116. package/dist/component/organism/Table/RowActions.js +121 -0
  117. package/dist/component/organism/Table/RowActions.js.map +1 -0
  118. package/dist/component/organism/Table/Table.d.ts +51 -0
  119. package/dist/component/organism/Table/Table.js +108 -0
  120. package/dist/component/organism/Table/Table.js.map +1 -0
  121. package/dist/component/organism/ViewTable/ColumnComparator.d.ts +11 -0
  122. package/dist/component/organism/ViewTable/ColumnComparator.js +25 -0
  123. package/dist/component/organism/ViewTable/ColumnComparator.js.map +1 -0
  124. package/dist/component/organism/ViewTable/ViewTable.d.ts +53 -0
  125. package/dist/component/organism/ViewTable/ViewTable.js +123 -0
  126. package/dist/component/organism/ViewTable/ViewTable.js.map +1 -0
  127. package/dist/component/template/CreateFormPage/CreateFormPage.d.ts +19 -0
  128. package/dist/component/template/CreateFormPage/CreateFormPage.js +41 -0
  129. package/dist/component/template/CreateFormPage/CreateFormPage.js.map +1 -0
  130. package/dist/component/template/EditFormPage/EditFormPage.d.ts +19 -0
  131. package/dist/component/template/EditFormPage/EditFormPage.js +42 -0
  132. package/dist/component/template/EditFormPage/EditFormPage.js.map +1 -0
  133. package/dist/component/template/FormPage/FormPage.d.ts +25 -0
  134. package/dist/component/template/FormPage/FormPage.js +130 -0
  135. package/dist/component/template/FormPage/FormPage.js.map +1 -0
  136. package/dist/component/template/FormPage/FormType.d.ts +6 -0
  137. package/dist/component/template/FormPage/FormType.js +12 -0
  138. package/dist/component/template/FormPage/FormType.js.map +1 -0
  139. package/dist/component/template/Layout/Layout.d.ts +21 -0
  140. package/dist/component/template/Layout/Layout.js +121 -0
  141. package/dist/component/template/Layout/Layout.js.map +1 -0
  142. package/dist/component/template/Layout/Layout.module.js +19 -0
  143. package/dist/component/template/Layout/Layout.module.js.map +1 -0
  144. package/dist/component/template/ListPage/ListPage.d.ts +32 -0
  145. package/dist/component/template/ListPage/ListPage.js +47 -0
  146. package/dist/component/template/ListPage/ListPage.js.map +1 -0
  147. package/dist/component/template/PrintPage/PrintPage.d.ts +25 -0
  148. package/dist/component/template/PrintPage/PrintPage.js +115 -0
  149. package/dist/component/template/PrintPage/PrintPage.js.map +1 -0
  150. package/dist/component/template/ViewPage/ViewPage.d.ts +11 -0
  151. package/dist/component/template/ViewPage/ViewPage.js +49 -0
  152. package/dist/component/template/ViewPage/ViewPage.js.map +1 -0
  153. package/dist/data/ListDataSource.d.ts +12 -0
  154. package/dist/data/ListDataSource.js +1 -0
  155. package/dist/data/SaveDataSource.d.ts +16 -0
  156. package/dist/data/SaveDataSource.js +1 -0
  157. package/dist/export/ExportCellText.d.ts +18 -0
  158. package/dist/export/ExportCellText.js +60 -0
  159. package/dist/export/ExportCellText.js.map +1 -0
  160. package/dist/export/ExportDocument.d.ts +127 -0
  161. package/dist/export/ExportDocument.js +59 -0
  162. package/dist/export/ExportDocument.js.map +1 -0
  163. package/dist/export/ExportDownload.d.ts +9 -0
  164. package/dist/export/ExportDownload.js +19 -0
  165. package/dist/export/ExportDownload.js.map +1 -0
  166. package/dist/export/ExportFileName.d.ts +11 -0
  167. package/dist/export/ExportFileName.js +24 -0
  168. package/dist/export/ExportFileName.js.map +1 -0
  169. package/dist/export/ExportFormat.d.ts +30 -0
  170. package/dist/export/ExportFormat.js +1 -0
  171. package/dist/export/ExportFormats.d.ts +12 -0
  172. package/dist/export/ExportFormats.js +16 -0
  173. package/dist/export/ExportFormats.js.map +1 -0
  174. package/dist/export/ExportTexts.d.ts +14 -0
  175. package/dist/export/ExportTexts.js +23 -0
  176. package/dist/export/ExportTexts.js.map +1 -0
  177. package/dist/export/csv/CsvFormat.d.ts +41 -0
  178. package/dist/export/csv/CsvFormat.js +91 -0
  179. package/dist/export/csv/CsvFormat.js.map +1 -0
  180. package/dist/export/xlsx/XlsxFormat.d.ts +35 -0
  181. package/dist/export/xlsx/XlsxFormat.js +66 -0
  182. package/dist/export/xlsx/XlsxFormat.js.map +1 -0
  183. package/dist/export/xlsx/XlsxNumberFormat.d.ts +8 -0
  184. package/dist/export/xlsx/XlsxNumberFormat.js +15 -0
  185. package/dist/export/xlsx/XlsxNumberFormat.js.map +1 -0
  186. package/dist/export/xlsx/XlsxSheetName.d.ts +12 -0
  187. package/dist/export/xlsx/XlsxSheetName.js +62 -0
  188. package/dist/export/xlsx/XlsxSheetName.js.map +1 -0
  189. package/dist/export/xlsx/XlsxSheetWriter.d.ts +67 -0
  190. package/dist/export/xlsx/XlsxSheetWriter.js +215 -0
  191. package/dist/export/xlsx/XlsxSheetWriter.js.map +1 -0
  192. package/dist/export/xlsx/XlsxStyle.d.ts +51 -0
  193. package/dist/export/xlsx/XlsxStyle.js +87 -0
  194. package/dist/export/xlsx/XlsxStyle.js.map +1 -0
  195. package/dist/hook/useIsMobile.d.ts +5 -0
  196. package/dist/hook/useIsMobile.js +16 -0
  197. package/dist/hook/useIsMobile.js.map +1 -0
  198. package/dist/hook/useKeyedService.d.ts +22 -0
  199. package/dist/hook/useKeyedService.js +38 -0
  200. package/dist/hook/useKeyedService.js.map +1 -0
  201. package/dist/hook/useLightColorSchemeOnPrint.d.ts +9 -0
  202. package/dist/hook/useLightColorSchemeOnPrint.js +36 -0
  203. package/dist/hook/useLightColorSchemeOnPrint.js.map +1 -0
  204. package/dist/hook/useService.d.ts +12 -0
  205. package/dist/hook/useService.js +29 -0
  206. package/dist/hook/useService.js.map +1 -0
  207. package/dist/http/ApiError.d.ts +13 -0
  208. package/dist/http/ApiError.js +22 -0
  209. package/dist/http/ApiError.js.map +1 -0
  210. package/dist/http/AxiosHttpClient.d.ts +21 -0
  211. package/dist/http/AxiosHttpClient.js +67 -0
  212. package/dist/http/AxiosHttpClient.js.map +1 -0
  213. package/dist/http/AxiosHttpClientConfig.d.ts +37 -0
  214. package/dist/http/AxiosHttpClientConfig.js +19 -0
  215. package/dist/http/AxiosHttpClientConfig.js.map +1 -0
  216. package/dist/i18n/KitLocale.d.ts +4 -0
  217. package/dist/i18n/KitLocale.js +7 -0
  218. package/dist/i18n/KitLocale.js.map +1 -0
  219. package/dist/i18n/KitMessages.d.ts +146 -0
  220. package/dist/i18n/KitMessages.js +1 -0
  221. package/dist/i18n/messages/enUS.d.ts +3 -0
  222. package/dist/i18n/messages/enUS.js +112 -0
  223. package/dist/i18n/messages/enUS.js.map +1 -0
  224. package/dist/i18n/messages/ptBR.d.ts +3 -0
  225. package/dist/i18n/messages/ptBR.js +97 -0
  226. package/dist/i18n/messages/ptBR.js.map +1 -0
  227. package/dist/i18n/resolveMessages.d.ts +13 -0
  228. package/dist/i18n/resolveMessages.js +29 -0
  229. package/dist/i18n/resolveMessages.js.map +1 -0
  230. package/dist/model/Identifiable.d.ts +7 -0
  231. package/dist/model/Identifiable.js +1 -0
  232. package/dist/provider/KitConfig.d.ts +26 -0
  233. package/dist/provider/KitConfig.js +1 -0
  234. package/dist/provider/KitContext.d.ts +9 -0
  235. package/dist/provider/KitContext.js +27 -0
  236. package/dist/provider/KitContext.js.map +1 -0
  237. package/dist/provider/KitProvider.d.ts +7 -0
  238. package/dist/provider/KitProvider.js +31 -0
  239. package/dist/provider/KitProvider.js.map +1 -0
  240. package/dist/provider/useKit.d.ts +15 -0
  241. package/dist/provider/useKit.js +28 -0
  242. package/dist/provider/useKit.js.map +1 -0
  243. package/dist/router/FormRouteSegments.d.ts +16 -0
  244. package/dist/router/FormRouteSegments.js +19 -0
  245. package/dist/router/FormRouteSegments.js.map +1 -0
  246. package/dist/router/RouterAdapter.d.ts +24 -0
  247. package/dist/router/RouterAdapter.js +1 -0
  248. package/dist/router/anchorRouter.d.ts +7 -0
  249. package/dist/router/anchorRouter.js +23 -0
  250. package/dist/router/anchorRouter.js.map +1 -0
  251. package/dist/styles/print.css +93 -0
  252. package/dist/styles.css +188 -0
  253. package/dist/util/ArrayUtil.d.ts +39 -0
  254. package/dist/util/ArrayUtil.js +48 -0
  255. package/dist/util/ArrayUtil.js.map +1 -0
  256. package/dist/util/ColorUtil.d.ts +7 -0
  257. package/dist/util/ColorUtil.js +16 -0
  258. package/dist/util/ColorUtil.js.map +1 -0
  259. package/dist/util/CompareUtil.d.ts +19 -0
  260. package/dist/util/CompareUtil.js +51 -0
  261. package/dist/util/CompareUtil.js.map +1 -0
  262. package/dist/util/DateUtil.d.ts +37 -0
  263. package/dist/util/DateUtil.js +53 -0
  264. package/dist/util/DateUtil.js.map +1 -0
  265. package/dist/util/DownloadUtil.d.ts +6 -0
  266. package/dist/util/DownloadUtil.js +25 -0
  267. package/dist/util/DownloadUtil.js.map +1 -0
  268. package/dist/util/EnumUtil.d.ts +19 -0
  269. package/dist/util/EnumUtil.js +32 -0
  270. package/dist/util/EnumUtil.js.map +1 -0
  271. package/dist/util/FormUtil.d.ts +8 -0
  272. package/dist/util/FormUtil.js +14 -0
  273. package/dist/util/FormUtil.js.map +1 -0
  274. package/dist/util/HtmlUtil.d.ts +8 -0
  275. package/dist/util/HtmlUtil.js +23 -0
  276. package/dist/util/HtmlUtil.js.map +1 -0
  277. package/dist/util/Notifications.d.ts +30 -0
  278. package/dist/util/Notifications.js +59 -0
  279. package/dist/util/Notifications.js.map +1 -0
  280. package/dist/util/NumberUtil.d.ts +19 -0
  281. package/dist/util/NumberUtil.js +33 -0
  282. package/dist/util/NumberUtil.js.map +1 -0
  283. package/dist/util/ObjectUtil.d.ts +22 -0
  284. package/dist/util/ObjectUtil.js +34 -0
  285. package/dist/util/ObjectUtil.js.map +1 -0
  286. package/dist/util/SearchParamsUtil.d.ts +23 -0
  287. package/dist/util/SearchParamsUtil.js +29 -0
  288. package/dist/util/SearchParamsUtil.js.map +1 -0
  289. package/dist/util/TransformData.d.ts +14 -0
  290. package/dist/util/TransformData.js +31 -0
  291. package/dist/util/TransformData.js.map +1 -0
  292. package/dist/util/ValidationUtil.d.ts +9 -0
  293. package/dist/util/ValidationUtil.js +16 -0
  294. package/dist/util/ValidationUtil.js.map +1 -0
  295. package/dist/util/parseActionsPageParams.d.ts +14 -0
  296. package/dist/util/parseActionsPageParams.js +29 -0
  297. package/dist/util/parseActionsPageParams.js.map +1 -0
  298. package/package.json +149 -5
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Layout.js","names":["classes"],"sources":["../../../../src/component/template/Layout/Layout.tsx"],"sourcesContent":["import {\n ActionIcon,\n AppShell,\n Avatar,\n Burger,\n Container,\n Group,\n Menu,\n Tooltip,\n UnstyledButton,\n useComputedColorScheme,\n useMantineColorScheme,\n useMantineTheme\n} from '@mantine/core';\nimport { useDisclosure, useMediaQuery, useMounted } from '@mantine/hooks';\nimport { IconMoon, IconSun } from '@tabler/icons-react';\nimport cx from 'clsx';\n\nimport AppMain from '../../atom/AppMain/AppMain';\nimport Navbar from '../../organism/Navbar/Navbar';\nimport { NavItem } from '../../organism/Navbar/NavItem';\nimport { useKitMessages } from '../../../provider/useKit';\nimport classes from './Layout.module.css';\n\ninterface Props {\n children: React.ReactNode;\n\n /** Brand of the app in the header (e.g. the logo with a link to the home page). */\n logo: React.ReactNode;\n\n /** Items of the side menu. */\n navItems: NavItem[];\n\n /** Content fixed at the bottom of the side menu (e.g. a link to log out). */\n navFooter?: React.ReactNode;\n\n /**\n * Items of the user menu (e.g. `Menu.Item`s for the profile and to log out), opened by the avatar in the header.\n * Without them, the avatar is not shown.\n */\n userMenu?: React.ReactNode;\n}\n\n/**\n * Structure of the pages of the app: header with the brand, the color scheme toggle and the user menu, collapsible side\n * menu and the content area.\n */\nexport const Layout = ({ children, logo, navItems, navFooter, userMenu }: Props) => {\n const messages = useKitMessages().layout;\n const [mobileOpened, { toggle: toggleMobile }] = useDisclosure();\n const [desktopOpened, { toggle: toggleDesktop }] = useDisclosure(true);\n const { setColorScheme } = useMantineColorScheme();\n const savedColorScheme = useComputedColorScheme('light', { getInitialValueInEffect: true });\n /* The server does not know the color scheme saved in the browser and always renders the light one. Using the saved\n scheme only after mounting keeps the button label equal to the server HTML (avoiding a hydration error). */\n const computedColorScheme = useMounted() ? savedColorScheme : 'light';\n const nextColorScheme = computedColorScheme === 'light' ? 'dark' : 'light';\n const colorSchemeLabel = nextColorScheme === 'dark' ? messages.enableDarkTheme : messages.enableLightTheme;\n\n const theme = useMantineTheme();\n const isDesktop = useMediaQuery(`(min-width: ${theme.breakpoints.sm})`);\n const isMobile = !isDesktop;\n const isOpened = isMobile ? mobileOpened : desktopOpened;\n const toggleBurgerFn = isMobile ? toggleMobile : toggleDesktop;\n\n return (\n <AppShell\n header={{ height: { base: 60, sm: 68 } }}\n navbar={{\n width: { base: 300 },\n breakpoint: 'sm',\n collapsed: { mobile: !mobileOpened, desktop: !desktopOpened }\n }}\n padding={0}\n >\n <AppShell.Header>\n <Group h=\"100%\" justify=\"space-between\" wrap=\"nowrap\" gap=\"xs\" px={{ base: 'xs', sm: 'md' }}>\n <Group wrap=\"nowrap\" className={cx(classes.shrinkable, classes.headerGap)}>\n <Burger\n opened={isOpened}\n onClick={toggleBurgerFn}\n size=\"sm\"\n aria-label={isOpened ? messages.collapseNavigation : messages.expandNavigation}\n aria-expanded={isOpened}\n className={classes.fixed}\n />\n\n {logo}\n </Group>\n\n <Group wrap=\"nowrap\" gap=\"xs\" className={classes.fixed}>\n <Tooltip label={colorSchemeLabel}>\n <ActionIcon\n onClick={() => setColorScheme(nextColorScheme)}\n variant=\"subtle\"\n size={40}\n radius=\"xl\"\n aria-label={colorSchemeLabel}\n >\n <IconSun className={cx(classes.icon, classes.light)} stroke={1.5} />\n <IconMoon className={cx(classes.icon, classes.dark)} stroke={1.5} />\n </ActionIcon>\n </Tooltip>\n\n {userMenu && (\n <Menu shadow=\"lg\" width={200}>\n {/* The Tooltip stays outside the Menu.Target: in Mantine 9, the Menu.Target passes the menu\n props to its direct child, and they would go to the Tooltip instead of the button. */}\n <Tooltip label={messages.userMenu}>\n <Menu.Target>\n <UnstyledButton aria-label={messages.userMenu} style={{ borderRadius: '50%' }}>\n <Avatar color={theme.primaryColor} radius=\"xl\" size={40} />\n </UnstyledButton>\n </Menu.Target>\n </Tooltip>\n <Menu.Dropdown>\n <Menu.Label tt=\"uppercase\" ta=\"center\" fw={600}>\n {messages.userMenuTitle}\n </Menu.Label>\n {userMenu}\n </Menu.Dropdown>\n </Menu>\n )}\n </Group>\n </Group>\n </AppShell.Header>\n\n <Navbar items={navItems} footer={navFooter} linkClickHandler={() => isMobile && toggleBurgerFn()} />\n\n <AppShell.Main>\n <AppMain>\n <Container p=\"md\" fluid>\n {children}\n </Container>\n </AppMain>\n </AppShell.Main>\n </AppShell>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;AA+CA,IAAa,UAAU,EAAE,UAAU,MAAM,UAAU,WAAW,eAAsB;CAChF,MAAM,WAAW,eAAe,CAAC,CAAC;CAClC,MAAM,CAAC,cAAc,EAAE,QAAQ,kBAAkB,cAAc;CAC/D,MAAM,CAAC,eAAe,EAAE,QAAQ,mBAAmB,cAAc,IAAI;CACrE,MAAM,EAAE,mBAAmB,sBAAsB;CACjD,MAAM,mBAAmB,uBAAuB,SAAS,EAAE,yBAAyB,KAAK,CAAC;CAI1F,MAAM,mBADsB,WAAW,IAAI,mBAAmB,aACd,UAAU,SAAS;CACnE,MAAM,mBAAmB,oBAAoB,SAAS,SAAS,kBAAkB,SAAS;CAE1F,MAAM,QAAQ,gBAAgB;CAE9B,MAAM,WAAW,CADC,cAAc,eAAe,MAAM,YAAY,GAAG,EAClD;CAClB,MAAM,WAAW,WAAW,eAAe;CAC3C,MAAM,iBAAiB,WAAW,eAAe;CAEjD,OACI,qBAAC,UAAD;EACI,QAAQ,EAAE,QAAQ;GAAE,MAAM;GAAI,IAAI;EAAG,EAAE;EACvC,QAAQ;GACJ,OAAO,EAAE,MAAM,IAAI;GACnB,YAAY;GACZ,WAAW;IAAE,QAAQ,CAAC;IAAc,SAAS,CAAC;GAAc;EAChE;EACA,SAAS;EAPb,UAAA;GASI,oBAAC,SAAS,QAAV,EAAA,UACI,qBAAC,OAAD;IAAO,GAAE;IAAO,SAAQ;IAAgB,MAAK;IAAS,KAAI;IAAK,IAAI;KAAE,MAAM;KAAM,IAAI;IAAK;IAA1F,UAAA,CACI,qBAAC,OAAD;KAAO,MAAK;KAAS,WAAW,GAAGA,sBAAQ,YAAYA,sBAAQ,SAAS;KAAxE,UAAA,CACI,oBAAC,QAAD;MACI,QAAQ;MACR,SAAS;MACT,MAAK;MACL,cAAY,WAAW,SAAS,qBAAqB,SAAS;MAC9D,iBAAe;MACf,WAAWA,sBAAQ;KACtB,CAAA,GAEA,IACE;IAEP,CAAA,GAAA,qBAAC,OAAD;KAAO,MAAK;KAAS,KAAI;KAAK,WAAWA,sBAAQ;KAAjD,UAAA,CACI,oBAAC,SAAD;MAAS,OAAO;MACZ,UAAA,qBAAC,YAAD;OACI,eAAe,eAAe,eAAe;OAC7C,SAAQ;OACR,MAAM;OACN,QAAO;OACP,cAAY;OALhB,UAAA,CAOI,oBAAC,SAAD;QAAS,WAAW,GAAGA,sBAAQ,MAAMA,sBAAQ,KAAK;QAAG,QAAQ;OAAM,CAAA,GACnE,oBAAC,UAAD;QAAU,WAAW,GAAGA,sBAAQ,MAAMA,sBAAQ,IAAI;QAAG,QAAQ;OAAM,CAAA,CAC3D;;KACP,CAAA,GAER,YACG,qBAAC,MAAD;MAAM,QAAO;MAAK,OAAO;MAAzB,UAAA,CAGI,oBAAC,SAAD;OAAS,OAAO,SAAS;OACrB,UAAA,oBAAC,KAAK,QAAN,EAAA,UACI,oBAAC,gBAAD;QAAgB,cAAY,SAAS;QAAU,OAAO,EAAE,cAAc,MAAM;QACxE,UAAA,oBAAC,QAAD;SAAQ,OAAO,MAAM;SAAc,QAAO;SAAK,MAAM;QAAK,CAAA;OAC9C,CAAA,EACP,CAAA;MACR,CAAA,GACT,qBAAC,KAAK,UAAN,EAAA,UAAA,CACI,oBAAC,KAAK,OAAN;OAAY,IAAG;OAAY,IAAG;OAAS,IAAI;OACtC,UAAA,SAAS;MACF,CAAA,GACX,QACU,EAAA,CAAA,CACb;KAEP,CAAA,CAAA;IACJ,CAAA,CAAA;GACM,CAAA,EAAA,CAAA;GAEjB,oBAAC,QAAD;IAAQ,OAAO;IAAU,QAAQ;IAAW,wBAAwB,YAAY,eAAe;GAAI,CAAA;GAEnG,oBAAC,SAAS,MAAV,EAAA,UACI,oBAAC,SAAD,EAAA,UACI,oBAAC,WAAD;IAAW,GAAE;IAAK,OAAA;IACb;GACM,CAAA,EACN,CAAA,EACE,CAAA;EACT;;AAElB"}
@@ -0,0 +1,19 @@
1
+ "use client";
2
+ // src/component/template/Layout/Layout.module.css
3
+ var shrinkable = "mk-Layout-module-shrinkable-JUv2C";
4
+ var fixed = "mk-Layout-module-fixed-Z1ueS";
5
+ var icon = "mk-Layout-module-icon-EDq-h";
6
+ var dark = "mk-Layout-module-dark-Zx9Wz";
7
+ var light = "mk-Layout-module-light--F7XT";
8
+ var headerGap = "mk-Layout-module-headerGap-VrPBg";
9
+ var Layout_module_default = {
10
+ shrinkable,
11
+ fixed,
12
+ icon,
13
+ dark,
14
+ light,
15
+ headerGap
16
+ };
17
+ export { dark, Layout_module_default as default, fixed, headerGap, icon, light, shrinkable };
18
+
19
+ //# sourceMappingURL=Layout.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Layout.module.js","names":[],"sources":["../../../../src/component/template/Layout/Layout.module.css"],"sourcesContent":[".shrinkable {\n min-width: 0;\n}\n\n.fixed {\n flex-shrink: 0;\n}\n\n.icon {\n width: 20px;\n height: 20px;\n}\n\n.dark {\n @mixin dark {\n display: none;\n }\n\n @mixin light {\n display: block;\n }\n}\n\n.light {\n @mixin light {\n display: none;\n }\n\n @mixin dark {\n display: block;\n }\n}\n\n/* Responsive spacing of the header groups: the `gap` prop of the Mantine Group accepts no values per breakpoint. */\n.headerGap {\n gap: var(--mantine-spacing-xs);\n\n @mixin larger-than $mantine-breakpoint-sm {\n gap: var(--mantine-spacing-md);\n }\n}\n"],"mappings":""}
@@ -0,0 +1,32 @@
1
+ import { ReactElement, ReactNode } from 'react';
2
+ import { DataTableColumn } from 'mantine-datatable';
3
+ import { ListDataSource } from '../../../data/ListDataSource';
4
+ import { Identifiable } from '../../../model/Identifiable';
5
+ import { BreadcrumbItem } from '../../molecule/Breadcrumb/Breadcrumb';
6
+ import { ActionsSettings } from '../../organism/Table/Table';
7
+ interface ListPageProps<T, S> {
8
+ /** Title of the page (e.g. "Regions"). */
9
+ title: string;
10
+ /** Plural name of the records, used in the title of the table card. */
11
+ titlePlural: string;
12
+ breadcrumbItems: BreadcrumbItem[];
13
+ /** Route of the "Add" button; absent for no button. */
14
+ addActionRoute?: string;
15
+ /** Source of the records and of their deletion. */
16
+ service: S;
17
+ tableColumns: DataTableColumn<T>[];
18
+ /** Base path of the pages of the records (e.g. `/region`). */
19
+ resourceBasePath: string;
20
+ actionsSettings?: Partial<ActionsSettings>;
21
+ /** Extra content above the table (e.g. filters). */
22
+ children?: ReactNode;
23
+ customFetchMethod?: () => Promise<T[]>;
24
+ /** Builds the URL opened to view a record. If absent, the default view route is used. */
25
+ getViewUrl?: (item: T) => string;
26
+ }
27
+ /**
28
+ * List page of records: header with the "Add" button, optional extra content (e.g. filters) and the table of the
29
+ * records, with the view, edit and delete actions.
30
+ */
31
+ declare function ListPage<M extends Identifiable, S extends ListDataSource<M>>(props: ListPageProps<M, S>): ReactElement;
32
+ export default ListPage;
@@ -0,0 +1,47 @@
1
+ "use client";
2
+ import { useDocumentTitle, useKitMessages } from "../../../provider/useKit.js";
3
+ import PaperCard from "../../molecule/PaperCard/PaperCard.js";
4
+ import PageHeader from "../../organism/PageHeader/PageHeader.js";
5
+ import Table from "../../organism/Table/Table.js";
6
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
+ import { Group, Stack, Text } from "@mantine/core";
8
+ // src/component/template/ListPage/ListPage.tsx
9
+ /**
10
+ * List page of records: header with the "Add" button, optional extra content (e.g. filters) and the table of the
11
+ * records, with the view, edit and delete actions.
12
+ */
13
+ function ListPage(props) {
14
+ const { title, titlePlural, breadcrumbItems, addActionRoute, service, tableColumns, resourceBasePath, actionsSettings, children, customFetchMethod, getViewUrl } = props;
15
+ const documentTitle = useDocumentTitle(title);
16
+ const messages = useKitMessages();
17
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("title", { children: documentTitle }), /* @__PURE__ */ jsxs(Stack, {
18
+ gap: "lg",
19
+ children: [
20
+ /* @__PURE__ */ jsx(PageHeader, {
21
+ title,
22
+ breadcrumbItems,
23
+ addActionRoute
24
+ }),
25
+ children && /* @__PURE__ */ jsx(Stack, { children }),
26
+ /* @__PURE__ */ jsxs(PaperCard, { children: [/* @__PURE__ */ jsx(Group, {
27
+ justify: "space-between",
28
+ mb: "md",
29
+ children: /* @__PURE__ */ jsx(Text, {
30
+ fz: "lg",
31
+ fw: 600,
32
+ children: messages.table.listTitle(titlePlural)
33
+ })
34
+ }), /* @__PURE__ */ jsx(Table, {
35
+ service,
36
+ basePath: resourceBasePath,
37
+ columns: tableColumns,
38
+ customFetchMethod,
39
+ actionsSettings,
40
+ getViewUrl
41
+ })] })
42
+ ]
43
+ })] });
44
+ }
45
+ export { ListPage as default };
46
+
47
+ //# sourceMappingURL=ListPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ListPage.js","names":["_Fragment"],"sources":["../../../../src/component/template/ListPage/ListPage.tsx"],"sourcesContent":["import { ReactElement, ReactNode } from 'react';\n\nimport { Group, Stack, Text } from '@mantine/core';\nimport { DataTableColumn } from 'mantine-datatable';\n\nimport { ListDataSource } from '../../../data/ListDataSource';\nimport { Identifiable } from '../../../model/Identifiable';\nimport { useDocumentTitle, useKitMessages } from '../../../provider/useKit';\nimport { BreadcrumbItem } from '../../molecule/Breadcrumb/Breadcrumb';\nimport PaperCard from '../../molecule/PaperCard/PaperCard';\nimport PageHeader from '../../organism/PageHeader/PageHeader';\nimport Table, { ActionsSettings } from '../../organism/Table/Table';\n\ninterface ListPageProps<T, S> {\n /** Title of the page (e.g. \"Regions\"). */\n title: string;\n\n /** Plural name of the records, used in the title of the table card. */\n titlePlural: string;\n breadcrumbItems: BreadcrumbItem[];\n\n /** Route of the \"Add\" button; absent for no button. */\n addActionRoute?: string;\n\n /** Source of the records and of their deletion. */\n service: S;\n tableColumns: DataTableColumn<T>[];\n\n /** Base path of the pages of the records (e.g. `/region`). */\n resourceBasePath: string;\n actionsSettings?: Partial<ActionsSettings>;\n\n /** Extra content above the table (e.g. filters). */\n children?: ReactNode;\n customFetchMethod?: () => Promise<T[]>;\n\n /** Builds the URL opened to view a record. If absent, the default view route is used. */\n getViewUrl?: (item: T) => string;\n}\n\n/**\n * List page of records: header with the \"Add\" button, optional extra content (e.g. filters) and the table of the\n * records, with the view, edit and delete actions.\n */\nfunction ListPage<M extends Identifiable, S extends ListDataSource<M>>(props: ListPageProps<M, S>): ReactElement {\n const {\n title,\n titlePlural,\n breadcrumbItems,\n addActionRoute,\n service,\n tableColumns,\n resourceBasePath,\n actionsSettings,\n children,\n customFetchMethod,\n getViewUrl\n } = props;\n const documentTitle = useDocumentTitle(title);\n const messages = useKitMessages();\n\n return (\n <>\n <title>{documentTitle}</title>\n <Stack gap=\"lg\">\n <PageHeader title={title} breadcrumbItems={breadcrumbItems} addActionRoute={addActionRoute} />\n {children && <Stack>{children}</Stack>}\n <PaperCard>\n <Group justify=\"space-between\" mb=\"md\">\n <Text fz=\"lg\" fw={600}>\n {messages.table.listTitle(titlePlural)}\n </Text>\n </Group>\n <Table<M, S>\n service={service}\n basePath={resourceBasePath}\n columns={tableColumns}\n customFetchMethod={customFetchMethod}\n actionsSettings={actionsSettings}\n getViewUrl={getViewUrl}\n />\n </PaperCard>\n </Stack>\n </>\n );\n}\n\nexport default ListPage;\n"],"mappings":";;;;;;;;;;;;AA4CA,SAAS,SAA8D,OAA0C;CAC7G,MAAM,EACF,OACA,aACA,iBACA,gBACA,SACA,cACA,kBACA,iBACA,UACA,mBACA,eACA;CACJ,MAAM,gBAAgB,iBAAiB,KAAK;CAC5C,MAAM,WAAW,eAAe;CAEhC,OACI,qBAAAA,UAAA,EAAA,UAAA,CACI,oBAAC,SAAD,EAAA,UAAQ,cAAqB,CAAA,GAC7B,qBAAC,OAAD;EAAO,KAAI;EAAX,UAAA;GACI,oBAAC,YAAD;IAAmB;IAAwB;IAAiC;GAAiB,CAAA;GAC5F,YAAY,oBAAC,OAAD,EAAQ,SAAgB,CAAA;GACrC,qBAAC,WAAD,EAAA,UAAA,CACI,oBAAC,OAAD;IAAO,SAAQ;IAAgB,IAAG;IAC9B,UAAA,oBAAC,MAAD;KAAM,IAAG;KAAK,IAAI;KACb,UAAA,SAAS,MAAM,UAAU,WAAW;IACnC,CAAA;GACH,CAAA,GACP,oBAAC,OAAD;IACa;IACT,UAAU;IACV,SAAS;IACU;IACF;IACL;GACf,CAAA,CACM,EAAA,CAAA;EACR;CACT,CAAA,CAAA,EAAA,CAAA;AAEV"}
@@ -0,0 +1,25 @@
1
+ import { ReactElement, ReactNode } from 'react';
2
+ import type { ExportInfo } from '../../../export/ExportDocument';
3
+ /** Paper orientation: portrait (default) or landscape, for wide tables (e.g. a year per column). */
4
+ export type PrintOrientation = 'portrait' | 'landscape';
5
+ type Props = {
6
+ /** Title of the report, shown in the header. */
7
+ title: string;
8
+ /** Context info shown below the title (e.g. the period and the filters). */
9
+ info?: ExportInfo[];
10
+ orientation?: PrintOrientation;
11
+ /** Name of the system, shown in the footer (e.g. "Data generated by My System"). */
12
+ systemName: string;
13
+ /** Logo shown on the left of the title (e.g. an `<img>` about 48 px high); absent to show none. */
14
+ logo?: ReactNode;
15
+ /** Content of the report: sections ({@link PrintSection}), tables and charts. */
16
+ children: ReactNode;
17
+ };
18
+ /**
19
+ * Common layout of the reports: an HTML page formatted to be printed or saved as PDF with the browser itself.
20
+ * It has the logo, the title, the generation date, the context and, at the end, a footer with the link of the system.
21
+ * The bar with the "Print" button and the tips of the print dialog is shown only on screen. The pagination (paper size,
22
+ * repeated table header, page numbers) comes from the `styles/print.css` of the library.
23
+ */
24
+ declare function PrintPage({ title, info, orientation, systemName, logo, children }: Props): ReactElement;
25
+ export default PrintPage;
@@ -0,0 +1,115 @@
1
+ "use client";
2
+ import { useLightColorSchemeOnPrint } from "../../../hook/useLightColorSchemeOnPrint.js";
3
+ import { useKitMessages } from "../../../provider/useKit.js";
4
+ import { useEffect, useState } from "react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { Alert, Anchor, Box, Button, Group, Stack, Text, Title } from "@mantine/core";
7
+ import { IconInfoCircle, IconPrinter } from "@tabler/icons-react";
8
+ // src/component/template/PrintPage/PrintPage.tsx
9
+ /** Size of the icons (px). */
10
+ var ICON_SIZE = 18;
11
+ /**
12
+ * Common layout of the reports: an HTML page formatted to be printed or saved as PDF with the browser itself.
13
+ * It has the logo, the title, the generation date, the context and, at the end, a footer with the link of the system.
14
+ * The bar with the "Print" button and the tips of the print dialog is shown only on screen. The pagination (paper size,
15
+ * repeated table header, page numbers) comes from the `styles/print.css` of the library.
16
+ */
17
+ function PrintPage({ title, info = [], orientation = "portrait", systemName, logo, children }) {
18
+ useLightColorSchemeOnPrint();
19
+ const messages = useKitMessages();
20
+ const [generatedAt, setGeneratedAt] = useState();
21
+ const [siteUrl, setSiteUrl] = useState("");
22
+ useEffect(() => {
23
+ setGeneratedAt(/* @__PURE__ */ new Date());
24
+ setSiteUrl(window.location.origin);
25
+ }, []);
26
+ return /* @__PURE__ */ jsxs(Box, {
27
+ "data-print-orientation": orientation,
28
+ p: {
29
+ base: "xs",
30
+ sm: "md"
31
+ },
32
+ children: [
33
+ /* @__PURE__ */ jsx(PrintToolbar, { messages: messages.print }),
34
+ /* @__PURE__ */ jsxs(Stack, {
35
+ component: "header",
36
+ gap: 4,
37
+ mb: "lg",
38
+ children: [
39
+ /* @__PURE__ */ jsxs(Group, {
40
+ gap: "sm",
41
+ wrap: "nowrap",
42
+ children: [logo, /* @__PURE__ */ jsx(Title, {
43
+ order: 1,
44
+ size: "h2",
45
+ c: "var(--mantine-primary-color-filled)",
46
+ children: title
47
+ })]
48
+ }),
49
+ generatedAt && /* @__PURE__ */ jsx(Text, {
50
+ size: "sm",
51
+ c: "dimmed",
52
+ fs: "italic",
53
+ children: messages.export.generatedAt(generatedAt)
54
+ }),
55
+ info.map((item) => /* @__PURE__ */ jsxs(Text, {
56
+ size: "sm",
57
+ children: [
58
+ /* @__PURE__ */ jsxs(Text, {
59
+ span: true,
60
+ fw: 700,
61
+ c: "dimmed",
62
+ children: [item.label, ":"]
63
+ }),
64
+ " ",
65
+ item.value
66
+ ]
67
+ }, item.label))
68
+ ]
69
+ }),
70
+ children,
71
+ /* @__PURE__ */ jsxs(Stack, {
72
+ component: "footer",
73
+ gap: 0,
74
+ mt: "xl",
75
+ "data-print-block": true,
76
+ children: [/* @__PURE__ */ jsx(Text, {
77
+ size: "xs",
78
+ c: "dimmed",
79
+ children: messages.export.footer(systemName)
80
+ }), siteUrl && /* @__PURE__ */ jsx(Anchor, {
81
+ href: siteUrl,
82
+ size: "xs",
83
+ children: siteUrl
84
+ })]
85
+ })
86
+ ]
87
+ });
88
+ }
89
+ /** Bar shown only on screen, with the print button and the tips about the options of the print dialog. */
90
+ function PrintToolbar({ messages }) {
91
+ return /* @__PURE__ */ jsxs(Group, {
92
+ "data-print-hidden": true,
93
+ justify: "space-between",
94
+ align: "flex-start",
95
+ mb: "md",
96
+ wrap: "wrap",
97
+ children: [/* @__PURE__ */ jsx(Alert, {
98
+ variant: "light",
99
+ icon: /* @__PURE__ */ jsx(IconInfoCircle, { size: ICON_SIZE }),
100
+ title: messages.pdfTipTitle,
101
+ style: {
102
+ flex: 1,
103
+ minWidth: 280
104
+ },
105
+ children: messages.pdfTip
106
+ }), /* @__PURE__ */ jsx(Button, {
107
+ leftSection: /* @__PURE__ */ jsx(IconPrinter, { size: ICON_SIZE }),
108
+ onClick: () => window.print(),
109
+ children: messages.printButton
110
+ })]
111
+ });
112
+ }
113
+ export { PrintPage as default };
114
+
115
+ //# sourceMappingURL=PrintPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PrintPage.js","names":[],"sources":["../../../../src/component/template/PrintPage/PrintPage.tsx"],"sourcesContent":["'use client';\n\nimport { ReactElement, ReactNode, useEffect, useState } from 'react';\n\nimport { Alert, Anchor, Box, Button, Group, Stack, Text, Title } from '@mantine/core';\nimport { IconInfoCircle, IconPrinter } from '@tabler/icons-react';\n\nimport type { ExportInfo } from '../../../export/ExportDocument';\nimport { useLightColorSchemeOnPrint } from '../../../hook/useLightColorSchemeOnPrint';\nimport { PrintMessages } from '../../../i18n/KitMessages';\nimport { useKitMessages } from '../../../provider/useKit';\n\n/** Size of the icons (px). */\nconst ICON_SIZE = 18;\n\n/** Paper orientation: portrait (default) or landscape, for wide tables (e.g. a year per column). */\nexport type PrintOrientation = 'portrait' | 'landscape';\n\ntype Props = {\n /** Title of the report, shown in the header. */\n title: string;\n\n /** Context info shown below the title (e.g. the period and the filters). */\n info?: ExportInfo[];\n\n orientation?: PrintOrientation;\n\n /** Name of the system, shown in the footer (e.g. \"Data generated by My System\"). */\n systemName: string;\n\n /** Logo shown on the left of the title (e.g. an `<img>` about 48 px high); absent to show none. */\n logo?: ReactNode;\n\n /** Content of the report: sections ({@link PrintSection}), tables and charts. */\n children: ReactNode;\n};\n\n/**\n * Common layout of the reports: an HTML page formatted to be printed or saved as PDF with the browser itself.\n * It has the logo, the title, the generation date, the context and, at the end, a footer with the link of the system.\n * The bar with the \"Print\" button and the tips of the print dialog is shown only on screen. The pagination (paper size,\n * repeated table header, page numbers) comes from the `styles/print.css` of the library.\n */\nfunction PrintPage({ title, info = [], orientation = 'portrait', systemName, logo, children }: Props): ReactElement {\n useLightColorSchemeOnPrint();\n const messages = useKitMessages();\n\n /* The generation date and the address of the system are read only in the browser, after mounting: on the server,\n the date would be another one and there is no `window`, so the HTML would differ from the one of the browser\n (hydration error). */\n const [generatedAt, setGeneratedAt] = useState<Date>();\n const [siteUrl, setSiteUrl] = useState('');\n useEffect(() => {\n setGeneratedAt(new Date());\n setSiteUrl(window.location.origin);\n }, []);\n\n return (\n <Box data-print-orientation={orientation} p={{ base: 'xs', sm: 'md' }}>\n <PrintToolbar messages={messages.print} />\n\n <Stack component=\"header\" gap={4} mb=\"lg\">\n <Group gap=\"sm\" wrap=\"nowrap\">\n {logo}\n <Title order={1} size=\"h2\" c=\"var(--mantine-primary-color-filled)\">\n {title}\n </Title>\n </Group>\n {generatedAt && (\n <Text size=\"sm\" c=\"dimmed\" fs=\"italic\">\n {messages.export.generatedAt(generatedAt)}\n </Text>\n )}\n {info.map(item => (\n <Text key={item.label} size=\"sm\">\n <Text span fw={700} c=\"dimmed\">\n {item.label}:\n </Text>{' '}\n {item.value}\n </Text>\n ))}\n </Stack>\n\n {children}\n\n <Stack component=\"footer\" gap={0} mt=\"xl\" data-print-block>\n <Text size=\"xs\" c=\"dimmed\">\n {messages.export.footer(systemName)}\n </Text>\n {siteUrl && (\n <Anchor href={siteUrl} size=\"xs\">\n {siteUrl}\n </Anchor>\n )}\n </Stack>\n </Box>\n );\n}\n\n/** Bar shown only on screen, with the print button and the tips about the options of the print dialog. */\nfunction PrintToolbar({ messages }: { messages: PrintMessages }): ReactElement {\n return (\n <Group data-print-hidden justify=\"space-between\" align=\"flex-start\" mb=\"md\" wrap=\"wrap\">\n <Alert\n variant=\"light\"\n icon={<IconInfoCircle size={ICON_SIZE} />}\n title={messages.pdfTipTitle}\n style={{ flex: 1, minWidth: 280 }}\n >\n {messages.pdfTip}\n </Alert>\n <Button leftSection={<IconPrinter size={ICON_SIZE} />} onClick={() => window.print()}>\n {messages.printButton}\n </Button>\n </Group>\n );\n}\n\nexport default PrintPage;\n"],"mappings":";;;;;;;;;AAaA,IAAM,YAAY;;;;;;;AA8BlB,SAAS,UAAU,EAAE,OAAO,OAAO,CAAC,GAAG,cAAc,YAAY,YAAY,MAAM,YAAiC;CAChH,2BAA2B;CAC3B,MAAM,WAAW,eAAe;CAKhC,MAAM,CAAC,aAAa,kBAAkB,SAAe;CACrD,MAAM,CAAC,SAAS,cAAc,SAAS,EAAE;CACzC,gBAAgB;EACZ,+BAAe,IAAI,KAAK,CAAC;EACzB,WAAW,OAAO,SAAS,MAAM;CACrC,GAAG,CAAC,CAAC;CAEL,OACI,qBAAC,KAAD;EAAK,0BAAwB;EAAa,GAAG;GAAE,MAAM;GAAM,IAAI;EAAK;EAApE,UAAA;GACI,oBAAC,cAAD,EAAc,UAAU,SAAS,MAAQ,CAAA;GAEzC,qBAAC,OAAD;IAAO,WAAU;IAAS,KAAK;IAAG,IAAG;IAArC,UAAA;KACI,qBAAC,OAAD;MAAO,KAAI;MAAK,MAAK;MAArB,UAAA,CACK,MACD,oBAAC,OAAD;OAAO,OAAO;OAAG,MAAK;OAAK,GAAE;OACxB,UAAA;MACE,CAAA,CACJ;;KACN,eACG,oBAAC,MAAD;MAAM,MAAK;MAAK,GAAE;MAAS,IAAG;MACzB,UAAA,SAAS,OAAO,YAAY,WAAW;KACtC,CAAA;KAET,KAAK,KAAI,SACN,qBAAC,MAAD;MAAuB,MAAK;MAA5B,UAAA;OACI,qBAAC,MAAD;QAAM,MAAA;QAAK,IAAI;QAAK,GAAE;QAAtB,UAAA,CACK,KAAK,OAAM,GACV;;OAAE;OACP,KAAK;MACJ;KALK,GAAA,KAAK,KAKV,CACT;IACE;;GAEN;GAED,qBAAC,OAAD;IAAO,WAAU;IAAS,KAAK;IAAG,IAAG;IAAK,oBAAA;IAA1C,UAAA,CACI,oBAAC,MAAD;KAAM,MAAK;KAAK,GAAE;KACb,UAAA,SAAS,OAAO,OAAO,UAAU;IAChC,CAAA,GACL,WACG,oBAAC,QAAD;KAAQ,MAAM;KAAS,MAAK;KACvB,UAAA;IACG,CAAA,CAET;;EACN;;AAEb;;AAGA,SAAS,aAAa,EAAE,YAAuD;CAC3E,OACI,qBAAC,OAAD;EAAO,qBAAA;EAAkB,SAAQ;EAAgB,OAAM;EAAa,IAAG;EAAK,MAAK;EAAjF,UAAA,CACI,oBAAC,OAAD;GACI,SAAQ;GACR,MAAM,oBAAC,gBAAD,EAAgB,MAAM,UAAY,CAAA;GACxC,OAAO,SAAS;GAChB,OAAO;IAAE,MAAM;IAAG,UAAU;GAAI;GAE/B,UAAA,SAAS;EACP,CAAA,GACP,oBAAC,QAAD;GAAQ,aAAa,oBAAC,aAAD,EAAa,MAAM,UAAY,CAAA;GAAG,eAAe,OAAO,MAAM;GAC9E,UAAA,SAAS;EACN,CAAA,CACL;;AAEf"}
@@ -0,0 +1,11 @@
1
+ import React, { ReactElement } from 'react';
2
+ import { BreadcrumbItem } from '../../molecule/Breadcrumb/Breadcrumb';
3
+ interface ViewPageProps {
4
+ /** Name of the record (e.g. "Region"). */
5
+ title: string;
6
+ breadcrumbItems: BreadcrumbItem[];
7
+ backRoute: string;
8
+ }
9
+ /** Page that shows a record, with the given content and the back button. */
10
+ declare function ViewPage(props: React.PropsWithChildren<ViewPageProps>): ReactElement;
11
+ export default ViewPage;
@@ -0,0 +1,49 @@
1
+ "use client";
2
+ import { useDocumentTitle, useKitConfig } from "../../../provider/useKit.js";
3
+ import PaperCard from "../../molecule/PaperCard/PaperCard.js";
4
+ import PageHeader from "../../organism/PageHeader/PageHeader.js";
5
+ import "react";
6
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
+ import { Box, Button, Grid, Stack, Text } from "@mantine/core";
8
+ import { IconArrowBack } from "@tabler/icons-react";
9
+ // src/component/template/ViewPage/ViewPage.tsx
10
+ /** Page that shows a record, with the given content and the back button. */
11
+ function ViewPage(props) {
12
+ const { title, breadcrumbItems, backRoute, children } = props;
13
+ const { router, messages } = useKitConfig();
14
+ const { Link } = router;
15
+ const pageTitle = `${messages.form.action.view} ${title}`;
16
+ const documentTitle = useDocumentTitle(pageTitle);
17
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("title", { children: documentTitle }), /* @__PURE__ */ jsxs(Stack, {
18
+ gap: "lg",
19
+ children: [/* @__PURE__ */ jsx(PageHeader, {
20
+ title: pageTitle,
21
+ breadcrumbItems: [...breadcrumbItems, {
22
+ title: pageTitle,
23
+ href: "#"
24
+ }]
25
+ }), /* @__PURE__ */ jsx(Grid, { children: /* @__PURE__ */ jsx(Grid.Col, {
26
+ span: {
27
+ base: 12,
28
+ lg: 12
29
+ },
30
+ children: /* @__PURE__ */ jsx(PaperCard, { children: /* @__PURE__ */ jsxs(Stack, { children: [
31
+ /* @__PURE__ */ jsx(Text, {
32
+ size: "lg",
33
+ fw: 600,
34
+ children: pageTitle
35
+ }),
36
+ children,
37
+ /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Button, {
38
+ leftSection: /* @__PURE__ */ jsx(IconArrowBack, { size: 16 }),
39
+ component: Link,
40
+ href: backRoute,
41
+ children: messages.common.back
42
+ }) })
43
+ ] }) })
44
+ }) })]
45
+ })] });
46
+ }
47
+ export { ViewPage as default };
48
+
49
+ //# sourceMappingURL=ViewPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ViewPage.js","names":["_Fragment"],"sources":["../../../../src/component/template/ViewPage/ViewPage.tsx"],"sourcesContent":["import React, { ReactElement } from 'react';\n\nimport { Box, Button, Grid, Stack, Text } from '@mantine/core';\nimport { IconArrowBack } from '@tabler/icons-react';\n\nimport { useDocumentTitle, useKitConfig } from '../../../provider/useKit';\nimport { BreadcrumbItem } from '../../molecule/Breadcrumb/Breadcrumb';\nimport PaperCard from '../../molecule/PaperCard/PaperCard';\nimport PageHeader from '../../organism/PageHeader/PageHeader';\n\ninterface ViewPageProps {\n /** Name of the record (e.g. \"Region\"). */\n title: string;\n breadcrumbItems: BreadcrumbItem[];\n backRoute: string;\n}\n\n/** Page that shows a record, with the given content and the back button. */\nfunction ViewPage(props: React.PropsWithChildren<ViewPageProps>): ReactElement {\n const { title, breadcrumbItems, backRoute, children } = props;\n const { router, messages } = useKitConfig();\n const { Link } = router;\n const pageTitle = `${messages.form.action.view} ${title}`;\n const documentTitle = useDocumentTitle(pageTitle);\n\n return (\n <>\n <title>{documentTitle}</title>\n <Stack gap=\"lg\">\n <PageHeader title={pageTitle} breadcrumbItems={[...breadcrumbItems, { title: pageTitle, href: '#' }]} />\n <Grid>\n <Grid.Col span={{ base: 12, lg: 12 }}>\n <PaperCard>\n <Stack>\n <Text size=\"lg\" fw={600}>\n {pageTitle}\n </Text>\n\n {children}\n\n <Box>\n <Button leftSection={<IconArrowBack size={16} />} component={Link} href={backRoute}>\n {messages.common.back}\n </Button>\n </Box>\n </Stack>\n </PaperCard>\n </Grid.Col>\n </Grid>\n </Stack>\n </>\n );\n}\n\nexport default ViewPage;\n"],"mappings":";;;;;;;;;;AAkBA,SAAS,SAAS,OAA6D;CAC3E,MAAM,EAAE,OAAO,iBAAiB,WAAW,aAAa;CACxD,MAAM,EAAE,QAAQ,aAAa,aAAa;CAC1C,MAAM,EAAE,SAAS;CACjB,MAAM,YAAY,GAAG,SAAS,KAAK,OAAO,KAAK,GAAG;CAClD,MAAM,gBAAgB,iBAAiB,SAAS;CAEhD,OACI,qBAAAA,UAAA,EAAA,UAAA,CACI,oBAAC,SAAD,EAAA,UAAQ,cAAqB,CAAA,GAC7B,qBAAC,OAAD;EAAO,KAAI;EAAX,UAAA,CACI,oBAAC,YAAD;GAAY,OAAO;GAAW,iBAAiB,CAAC,GAAG,iBAAiB;IAAE,OAAO;IAAW,MAAM;GAAI,CAAC;EAAI,CAAA,GACvG,oBAAC,MAAD,EAAA,UACI,oBAAC,KAAK,KAAN;GAAU,MAAM;IAAE,MAAM;IAAI,IAAI;GAAG;GAC/B,UAAA,oBAAC,WAAD,EAAA,UACI,qBAAC,OAAD,EAAA,UAAA;IACI,oBAAC,MAAD;KAAM,MAAK;KAAK,IAAI;KACf,UAAA;IACC,CAAA;IAEL;IAED,oBAAC,KAAD,EAAA,UACI,oBAAC,QAAD;KAAQ,aAAa,oBAAC,eAAD,EAAe,MAAM,GAAK,CAAA;KAAG,WAAW;KAAM,MAAM;KACpE,UAAA,SAAS,OAAO;IACb,CAAA,EACP,CAAA;GACF,EAAA,CAAA,EACA,CAAA;EACL,CAAA,EACR,CAAA,CACH;CACT,CAAA,CAAA,EAAA,CAAA;AAEV"}
@@ -0,0 +1,12 @@
1
+ import { Identifiable } from '../model/Identifiable';
2
+ /**
3
+ * Source of the records of a table that allows deleting them (e.g. a service that accesses a REST API). Any object
4
+ * with these methods works, without extending a class.
5
+ * @template M type of the records
6
+ */
7
+ export interface ListDataSource<M extends Identifiable> {
8
+ /** Fetches all records shown in the table. */
9
+ findAll(): Promise<M[]>;
10
+ /** Deletes the record with the given id. */
11
+ delete(id: number | string): Promise<void>;
12
+ }
@@ -0,0 +1 @@
1
+ "use client";
@@ -0,0 +1,16 @@
1
+ import { Identifiable } from '../model/Identifiable';
2
+ /**
3
+ * Destination of the data of a form: creates a record (without an id) or updates an existing one (with an id). Any
4
+ * object with this method works, without extending a class.
5
+ * @template M type of the saved record, returned by the destination
6
+ * @template D type of the data sent by the form (e.g. a DTO, or M itself)
7
+ */
8
+ export interface SaveDataSource<M extends Identifiable, D> {
9
+ /**
10
+ * Creates or updates a record.
11
+ * @param id id of the record to update; if absent, the record is created
12
+ * @param data data to save
13
+ * @return the saved record
14
+ */
15
+ save(id: M['id'] | string | undefined, data: D): Promise<M>;
16
+ }
@@ -0,0 +1 @@
1
+ "use client";
@@ -0,0 +1,18 @@
1
+ import { ClassifiedCell, NumberFormat } from './ExportDocument';
2
+ /**
3
+ * Formats a number as a spreadsheet in the language of the locale shows it (e.g. a decimal comma in `pt-BR`).
4
+ * @param value number; a percentage is in the 0..1 scale
5
+ * @param format decimal places and whether the value is a percentage
6
+ * @param grouping whether the thousands separator is used (e.g. "1.234,56" in `pt-BR`); `false` gives "1234,56"
7
+ * @param locale locale of the format; defaults to `en-US`
8
+ * @return the formatted number, with "%" at the end if it is a percentage
9
+ */
10
+ export declare function formatNumber(value: number, format: NumberFormat, grouping?: boolean, locale?: string): string;
11
+ /**
12
+ * Returns the text of a cell, as the user sees it.
13
+ * @param cell cell already classified
14
+ * @param grouping whether the numbers use the thousands separator
15
+ * @param locale locale of the number format; defaults to `en-US`
16
+ * @return the text of the cell; empty for an absent value
17
+ */
18
+ export declare function cellText(cell: ClassifiedCell, grouping?: boolean, locale?: string): string;
@@ -0,0 +1,60 @@
1
+ "use client";
2
+ import { DEFAULT_LOCALE } from "../i18n/KitLocale.js";
3
+ // src/export/ExportCellText.ts
4
+ /** Multiplier that converts a percentage from the 0..1 scale to the 0..100 display scale. */
5
+ var PERCENT_SCALE = 100;
6
+ /**
7
+ * Formatters already created, by locale and format. Creating an `Intl.NumberFormat` is expensive, and the export
8
+ * formats every cell (e.g. to measure the column widths), but there are few combinations of locale, decimal places and
9
+ * thousands separator.
10
+ */
11
+ var formatters = /* @__PURE__ */ new Map();
12
+ /**
13
+ * Returns the number formatter of a locale for the given decimal places and thousands separator.
14
+ * @param locale locale of the format
15
+ * @param decimals decimal places
16
+ * @param grouping whether the thousands separator is used
17
+ * @return the formatter, created only the first time
18
+ */
19
+ function numberFormatter(locale, decimals, grouping) {
20
+ const key = `${locale}:${decimals}:${grouping}`;
21
+ let formatter = formatters.get(key);
22
+ if (!formatter) {
23
+ formatter = new Intl.NumberFormat(locale, {
24
+ minimumFractionDigits: decimals,
25
+ maximumFractionDigits: decimals,
26
+ useGrouping: grouping
27
+ });
28
+ formatters.set(key, formatter);
29
+ }
30
+ return formatter;
31
+ }
32
+ /**
33
+ * Formats a number as a spreadsheet in the language of the locale shows it (e.g. a decimal comma in `pt-BR`).
34
+ * @param value number; a percentage is in the 0..1 scale
35
+ * @param format decimal places and whether the value is a percentage
36
+ * @param grouping whether the thousands separator is used (e.g. "1.234,56" in `pt-BR`); `false` gives "1234,56"
37
+ * @param locale locale of the format; defaults to `en-US`
38
+ * @return the formatted number, with "%" at the end if it is a percentage
39
+ */
40
+ function formatNumber(value, format, grouping = true, locale = DEFAULT_LOCALE) {
41
+ const formatter = numberFormatter(locale, format.decimals, grouping);
42
+ return format.percent ? `${formatter.format(value * PERCENT_SCALE)}%` : formatter.format(value);
43
+ }
44
+ /**
45
+ * Returns the text of a cell, as the user sees it.
46
+ * @param cell cell already classified
47
+ * @param grouping whether the numbers use the thousands separator
48
+ * @param locale locale of the number format; defaults to `en-US`
49
+ * @return the text of the cell; empty for an absent value
50
+ */
51
+ function cellText(cell, grouping = true, locale = DEFAULT_LOCALE) {
52
+ switch (cell.kind) {
53
+ case "empty": return "";
54
+ case "number": return formatNumber(cell.value, cell.format, grouping, locale);
55
+ default: return cell.text;
56
+ }
57
+ }
58
+ export { cellText, formatNumber };
59
+
60
+ //# sourceMappingURL=ExportCellText.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExportCellText.js","names":[],"sources":["../../src/export/ExportCellText.ts"],"sourcesContent":["import { DEFAULT_LOCALE } from '../i18n/KitLocale';\nimport { ClassifiedCell, NumberFormat } from './ExportDocument';\n\n/** Multiplier that converts a percentage from the 0..1 scale to the 0..100 display scale. */\nconst PERCENT_SCALE = 100;\n\n/**\n * Formatters already created, by locale and format. Creating an `Intl.NumberFormat` is expensive, and the export\n * formats every cell (e.g. to measure the column widths), but there are few combinations of locale, decimal places and\n * thousands separator.\n */\nconst formatters = new Map<string, Intl.NumberFormat>();\n\n/**\n * Returns the number formatter of a locale for the given decimal places and thousands separator.\n * @param locale locale of the format\n * @param decimals decimal places\n * @param grouping whether the thousands separator is used\n * @return the formatter, created only the first time\n */\nfunction numberFormatter(locale: string, decimals: number, grouping: boolean): Intl.NumberFormat {\n const key = `${locale}:${decimals}:${grouping}`;\n let formatter = formatters.get(key);\n if (!formatter) {\n formatter = new Intl.NumberFormat(locale, {\n minimumFractionDigits: decimals,\n maximumFractionDigits: decimals,\n useGrouping: grouping\n });\n formatters.set(key, formatter);\n }\n\n return formatter;\n}\n\n/**\n * Formats a number as a spreadsheet in the language of the locale shows it (e.g. a decimal comma in `pt-BR`).\n * @param value number; a percentage is in the 0..1 scale\n * @param format decimal places and whether the value is a percentage\n * @param grouping whether the thousands separator is used (e.g. \"1.234,56\" in `pt-BR`); `false` gives \"1234,56\"\n * @param locale locale of the format; defaults to `en-US`\n * @return the formatted number, with \"%\" at the end if it is a percentage\n */\nexport function formatNumber(\n value: number,\n format: NumberFormat,\n grouping: boolean = true,\n locale: string = DEFAULT_LOCALE\n): string {\n const formatter = numberFormatter(locale, format.decimals, grouping);\n\n return format.percent ? `${formatter.format(value * PERCENT_SCALE)}%` : formatter.format(value);\n}\n\n/**\n * Returns the text of a cell, as the user sees it.\n * @param cell cell already classified\n * @param grouping whether the numbers use the thousands separator\n * @param locale locale of the number format; defaults to `en-US`\n * @return the text of the cell; empty for an absent value\n */\nexport function cellText(cell: ClassifiedCell, grouping: boolean = true, locale: string = DEFAULT_LOCALE): string {\n switch (cell.kind) {\n case 'empty':\n return '';\n case 'number':\n return formatNumber(cell.value, cell.format, grouping, locale);\n default:\n return cell.text;\n }\n}\n"],"mappings":";;;;AAIA,IAAM,gBAAgB;;;;;;AAOtB,IAAM,6BAAa,IAAI,IAA+B;;;;;;;;AAStD,SAAS,gBAAgB,QAAgB,UAAkB,UAAsC;CAC7F,MAAM,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG;CACrC,IAAI,YAAY,WAAW,IAAI,GAAG;CAClC,IAAI,CAAC,WAAW;EACZ,YAAY,IAAI,KAAK,aAAa,QAAQ;GACtC,uBAAuB;GACvB,uBAAuB;GACvB,aAAa;EACjB,CAAC;EACD,WAAW,IAAI,KAAK,SAAS;CACjC;CAEA,OAAO;AACX;;;;;;;;;AAUA,SAAgB,aACZ,OACA,QACA,WAAoB,MACpB,SAAiB,gBACX;CACN,MAAM,YAAY,gBAAgB,QAAQ,OAAO,UAAU,QAAQ;CAEnE,OAAO,OAAO,UAAU,GAAG,UAAU,OAAO,QAAQ,aAAa,EAAE,KAAK,UAAU,OAAO,KAAK;AAClG;;;;;;;;AASA,SAAgB,SAAS,MAAsB,WAAoB,MAAM,SAAiB,gBAAwB;CAC9G,QAAQ,KAAK,MAAb;EACI,KAAK,SACD,OAAO;EACX,KAAK,UACD,OAAO,aAAa,KAAK,OAAO,KAAK,QAAQ,UAAU,MAAM;EACjE,SACI,OAAO,KAAK;CACpB;AACJ"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Model of the exported data, independent of the file format (see `ExportFormat`). An export is a document with one
3
+ * or more sheets, and each sheet is a matrix (an array of arrays) of cells, with the title of each column.
4
+ * It depends on no domain: whoever exports converts their data to this model.
5
+ * @author Manoel Campos
6
+ */
7
+ import { KitLocale } from '../i18n/KitLocale';
8
+ import { ExportMessages } from '../i18n/KitMessages';
9
+ /** Format of a numeric value. Percentages are in the 0..1 scale and converted only for display. */
10
+ export type NumberFormat = {
11
+ /** Decimal places shown. */
12
+ decimals: number;
13
+ /** Whether the value is a percentage in the 0..1 scale (e.g. 0.85 is shown as 85%). */
14
+ percent?: boolean;
15
+ };
16
+ /** Number with its own format, for when the format changes from one row to another (e.g. the unit of each row). */
17
+ export type NumberCell = {
18
+ value: number;
19
+ format: NumberFormat;
20
+ };
21
+ /** Cell whose value could not be computed (e.g. a calculation error), unlike an empty (absent) cell. */
22
+ export type InvalidCell = {
23
+ invalid: true;
24
+ /** Text shown instead of the value. */
25
+ text: string;
26
+ };
27
+ /**
28
+ * Value of a cell:
29
+ * - `string`: text;
30
+ * - `number`: number, in the format of the column (`NaN` is treated as an absent value);
31
+ * - {@link NumberCell}: number with its own format;
32
+ * - {@link InvalidCell}: invalid result;
33
+ * - `undefined`: absent value (empty cell), which is different from zero.
34
+ */
35
+ export type ExportCell = string | number | NumberCell | InvalidCell | undefined;
36
+ /** Column of a sheet. */
37
+ export type ExportColumn = {
38
+ /** Title (header) of the column. */
39
+ header: string;
40
+ /** Format of the numbers of the column, used when the cell has none; absent for {@link DEFAULT_NUMBER_FORMAT}. */
41
+ format?: NumberFormat;
42
+ };
43
+ /** Sheet of the file: a table with the columns and the rows. */
44
+ export type ExportSheet = {
45
+ /** Name of the sheet. Each format adapts it to its rules (e.g. the maximum length in Excel). */
46
+ name: string;
47
+ columns: ExportColumn[];
48
+ /**
49
+ * One array per row, with one cell per column, in the order of {@link columns}. A shorter row is completed with
50
+ * empty cells; a row with more cells than columns is an error, since the extra data would be lost.
51
+ */
52
+ rows: ExportCell[][];
53
+ };
54
+ /** Information about the context of the data, shown at the beginning of the file (e.g. the period and the filters). */
55
+ export type ExportInfo = {
56
+ label: string;
57
+ value: string;
58
+ };
59
+ /** Visual identity of the system that generated the file, shown in the header and in the footer. */
60
+ export type ExportBranding = {
61
+ /** Name of the system, shown in the footer (e.g. "Data generated by My System"). */
62
+ systemName: string;
63
+ /** Address of the system, shown as a link in the footer. */
64
+ siteUrl: string;
65
+ /** Logo shown in the header; absent to show no logo (e.g. if it could not be loaded). */
66
+ logo?: ExportImage;
67
+ };
68
+ /** PNG image embedded in the file. */
69
+ export type ExportImage = {
70
+ /** Content of the image, as a base64 data URL (`data:image/png;base64,...`). */
71
+ pngDataUrl: string;
72
+ /** Original width and height (px), to keep the aspect ratio when resizing. */
73
+ width: number;
74
+ height: number;
75
+ };
76
+ /** Document to export: the data and its context. */
77
+ export type ExportDocument = {
78
+ /** Title shown at the top of the file. */
79
+ title: string;
80
+ /** Name of the file, without the date and the extension, which are added on export. */
81
+ fileName: string;
82
+ info: ExportInfo[];
83
+ /** Date and time the data was generated. */
84
+ generatedAt: Date;
85
+ branding: ExportBranding;
86
+ sheets: ExportSheet[];
87
+ /** Locale of the texts and of the number format of the file. Default: `en-US`. */
88
+ locale?: KitLocale;
89
+ /** Texts that replace the ones of the locale (e.g. the ones the app overrides in the `KitProvider`). */
90
+ messages?: Partial<ExportMessages>;
91
+ };
92
+ /** Format of the numbers of a column that defines none. */
93
+ export declare const DEFAULT_NUMBER_FORMAT: NumberFormat;
94
+ /** Types of cell, after being normalized by {@link classifyCell}. */
95
+ export type ClassifiedCell = {
96
+ kind: 'empty';
97
+ } | {
98
+ kind: 'text';
99
+ text: string;
100
+ } | {
101
+ kind: 'number';
102
+ value: number;
103
+ format: NumberFormat;
104
+ } | {
105
+ kind: 'invalid';
106
+ text: string;
107
+ };
108
+ /**
109
+ * Creates a cell with an invalid result.
110
+ * @param text text shown instead of the value; defaults to the text of the default locale
111
+ * @return the invalid cell
112
+ */
113
+ export declare function invalidCell(text?: string): InvalidCell;
114
+ /**
115
+ * Tells whether the cell is an invalid result.
116
+ * @param cell cell to check
117
+ */
118
+ export declare function isInvalidCell(cell: ExportCell): cell is InvalidCell;
119
+ /**
120
+ * Classifies a cell, so that every format handles each type of value the same way. A `NaN` number is treated as
121
+ * absent (empty cell), and `Infinity` as invalid (e.g. a division by zero).
122
+ * @param cell cell to classify
123
+ * @param columnFormat format of the column of the cell, used when the cell is a number without its own format
124
+ * @param invalidText text of an infinite number; defaults to the text of the default locale
125
+ * @return the type and the value of the cell
126
+ */
127
+ export declare function classifyCell(cell: ExportCell, columnFormat?: NumberFormat, invalidText?: string): ClassifiedCell;