wcz-layout 6.7.2 → 9.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (271) hide show
  1. package/dist/Approval-Co6D1BNq.mjs +194 -0
  2. package/dist/Approval-Co6D1BNq.mjs.map +1 -0
  3. package/dist/DialogsContext-DLqA8RJ_.mjs +7 -0
  4. package/dist/DialogsContext-DLqA8RJ_.mjs.map +1 -0
  5. package/dist/Email-BzQQkbe9.mjs +20 -0
  6. package/dist/Email-BzQQkbe9.mjs.map +1 -0
  7. package/dist/FileMeta-DDqUju1Y.mjs +19 -0
  8. package/dist/FileMeta-DDqUju1Y.mjs.map +1 -0
  9. package/dist/FileMeta-ILLTOjaM.d.mts +20 -0
  10. package/dist/NotificationContext-CgwUOeW0.mjs +7 -0
  11. package/dist/NotificationContext-CgwUOeW0.mjs.map +1 -0
  12. package/dist/QueryClientParam-CzaM3akD.d.mts +11 -0
  13. package/dist/RouterListItemButton-owZVvuC_.mjs +78 -0
  14. package/dist/RouterListItemButton-owZVvuC_.mjs.map +1 -0
  15. package/dist/User-1gKoYJvW.d.mts +12 -0
  16. package/dist/auth.d.mts +25 -0
  17. package/dist/auth.mjs +88 -0
  18. package/dist/auth.mjs.map +1 -0
  19. package/dist/authMiddleware--HdlhhZO.mjs +78 -0
  20. package/dist/authMiddleware--HdlhhZO.mjs.map +1 -0
  21. package/dist/components.d.mts +107 -0
  22. package/dist/components.mjs +1500 -0
  23. package/dist/components.mjs.map +1 -0
  24. package/dist/data/client.d.mts +3217 -0
  25. package/dist/data/client.mjs +187 -0
  26. package/dist/data/client.mjs.map +1 -0
  27. package/dist/data/server.d.mts +19 -0
  28. package/dist/data/server.mjs +16 -0
  29. package/dist/data/server.mjs.map +1 -0
  30. package/dist/entra-s4ZjHq5o.mjs +101 -0
  31. package/dist/entra-s4ZjHq5o.mjs.map +1 -0
  32. package/dist/env-CoveIivr.mjs +30 -0
  33. package/dist/env-CoveIivr.mjs.map +1 -0
  34. package/dist/file-C5-a_6W6.mjs +148 -0
  35. package/dist/file-C5-a_6W6.mjs.map +1 -0
  36. package/dist/file-DM1x40eJ.mjs +179 -0
  37. package/dist/file-DM1x40eJ.mjs.map +1 -0
  38. package/dist/hooks.d.mts +226 -0
  39. package/dist/hooks.mjs +1087 -0
  40. package/dist/hooks.mjs.map +1 -0
  41. package/dist/index.d.mts +48 -0
  42. package/dist/index.mjs +1944 -0
  43. package/dist/index.mjs.map +1 -0
  44. package/dist/middleware.d.mts +46 -0
  45. package/dist/middleware.mjs +27 -0
  46. package/dist/middleware.mjs.map +1 -0
  47. package/dist/models.d.mts +598 -0
  48. package/dist/models.mjs +74 -0
  49. package/dist/models.mjs.map +1 -0
  50. package/dist/msalServer-CkNOOjjH.mjs +44 -0
  51. package/dist/msalServer-CkNOOjjH.mjs.map +1 -0
  52. package/dist/peoplesoft-DIe8H1Nu.mjs +240 -0
  53. package/dist/peoplesoft-DIe8H1Nu.mjs.map +1 -0
  54. package/dist/peoplesoft-gKd-Jh5L.d.mts +1219 -0
  55. package/dist/useDialogs-BUzVrTSP.mjs +248 -0
  56. package/dist/useDialogs-BUzVrTSP.mjs.map +1 -0
  57. package/dist/user-Cen43mlr.d.mts +19 -0
  58. package/dist/utils-2XiozDlV.mjs +156 -0
  59. package/dist/utils-2XiozDlV.mjs.map +1 -0
  60. package/dist/utils-BuWEQOuy.d.mts +65 -0
  61. package/dist/utils.d.mts +5 -0
  62. package/dist/utils.mjs +5 -0
  63. package/dist/vite.d.mts +7 -0
  64. package/dist/vite.mjs +182 -0
  65. package/dist/vite.mjs.map +1 -0
  66. package/package.json +129 -62
  67. package/skills/client-db/SKILL.md +93 -0
  68. package/skills/data-grid/SKILL.md +142 -0
  69. package/skills/db-schema/SKILL.md +71 -0
  70. package/skills/dialogs/SKILL.md +79 -0
  71. package/skills/forms/SKILL.md +82 -0
  72. package/skills/general/SKILL.md +17 -0
  73. package/skills/notifications/SKILL.md +43 -0
  74. package/skills/routing/SKILL.md +128 -0
  75. package/skills/server-functions/SKILL.md +113 -0
  76. package/skills/services/SKILL.md +30 -0
  77. package/skills/services/docs/approval.md +257 -0
  78. package/skills/services/docs/email.md +32 -0
  79. package/skills/services/docs/file.md +81 -0
  80. package/skills/services/docs/peoplesoft.md +110 -0
  81. package/skills/start/SKILL.md +46 -0
  82. package/skills/start/steps/01-git-setup.md +11 -0
  83. package/skills/start/steps/02-project-name-setup.md +14 -0
  84. package/skills/start/steps/03-apm-setup.md +208 -0
  85. package/skills/start/steps/04-database-setup.md +39 -0
  86. package/skills/start/steps/05-entra-setup.md +59 -0
  87. package/skills/start/steps/06-vault-setup.md +70 -0
  88. package/skills/start/steps/07-generate-favicon.md +10 -0
  89. package/skills/start/steps/08-commit.md +15 -0
  90. package/dist/src/components/Layout.d.ts +0 -16
  91. package/dist/src/components/Layout.js +0 -122
  92. package/dist/src/components/Layout.js.map +0 -1
  93. package/dist/src/components/dataGrid/ChipInputCell.d.ts +0 -9
  94. package/dist/src/components/dataGrid/ChipInputCell.js +0 -17
  95. package/dist/src/components/dataGrid/ChipInputCell.js.map +0 -1
  96. package/dist/src/components/dataGrid/EditableColumnHeader.d.ts +0 -2
  97. package/dist/src/components/dataGrid/EditableColumnHeader.js +0 -7
  98. package/dist/src/components/dataGrid/EditableColumnHeader.js.map +0 -1
  99. package/dist/src/components/dataGrid/GridToolbar.d.ts +0 -8
  100. package/dist/src/components/dataGrid/GridToolbar.js +0 -40
  101. package/dist/src/components/dataGrid/GridToolbar.js.map +0 -1
  102. package/dist/src/components/dataGrid/TableContainer.d.ts +0 -3
  103. package/dist/src/components/dataGrid/TableContainer.js +0 -32
  104. package/dist/src/components/dataGrid/TableContainer.js.map +0 -1
  105. package/dist/src/components/form/FormAutocomplete.d.ts +0 -7
  106. package/dist/src/components/form/FormAutocomplete.js +0 -10
  107. package/dist/src/components/form/FormAutocomplete.js.map +0 -1
  108. package/dist/src/components/form/FormCheckbox.d.ts +0 -7
  109. package/dist/src/components/form/FormCheckbox.js +0 -11
  110. package/dist/src/components/form/FormCheckbox.js.map +0 -1
  111. package/dist/src/components/form/FormDatePicker.d.ts +0 -9
  112. package/dist/src/components/form/FormDatePicker.js +0 -19
  113. package/dist/src/components/form/FormDatePicker.js.map +0 -1
  114. package/dist/src/components/form/FormDateTimePicker.d.ts +0 -9
  115. package/dist/src/components/form/FormDateTimePicker.js +0 -19
  116. package/dist/src/components/form/FormDateTimePicker.js.map +0 -1
  117. package/dist/src/components/form/FormNumberField.d.ts +0 -12
  118. package/dist/src/components/form/FormNumberField.js +0 -12
  119. package/dist/src/components/form/FormNumberField.js.map +0 -1
  120. package/dist/src/components/form/FormRadioGroup.d.ts +0 -13
  121. package/dist/src/components/form/FormRadioGroup.js +0 -11
  122. package/dist/src/components/form/FormRadioGroup.js.map +0 -1
  123. package/dist/src/components/form/FormSlider.d.ts +0 -7
  124. package/dist/src/components/form/FormSlider.js +0 -11
  125. package/dist/src/components/form/FormSlider.js.map +0 -1
  126. package/dist/src/components/form/FormSubmitButton.d.ts +0 -5
  127. package/dist/src/components/form/FormSubmitButton.js +0 -13
  128. package/dist/src/components/form/FormSubmitButton.js.map +0 -1
  129. package/dist/src/components/form/FormSwitch.d.ts +0 -7
  130. package/dist/src/components/form/FormSwitch.js +0 -11
  131. package/dist/src/components/form/FormSwitch.js.map +0 -1
  132. package/dist/src/components/form/FormTextField.d.ts +0 -7
  133. package/dist/src/components/form/FormTextField.js +0 -11
  134. package/dist/src/components/form/FormTextField.js.map +0 -1
  135. package/dist/src/components/layout/AccountMenu.d.ts +0 -9
  136. package/dist/src/components/layout/AccountMenu.js +0 -44
  137. package/dist/src/components/layout/AccountMenu.js.map +0 -1
  138. package/dist/src/components/layout/DevelopmentBanner.d.ts +0 -7
  139. package/dist/src/components/layout/DevelopmentBanner.js +0 -29
  140. package/dist/src/components/layout/DevelopmentBanner.js.map +0 -1
  141. package/dist/src/components/layout/ErrorPage.d.ts +0 -2
  142. package/dist/src/components/layout/ErrorPage.js +0 -25
  143. package/dist/src/components/layout/ErrorPage.js.map +0 -1
  144. package/dist/src/components/layout/LayoutDialog.d.ts +0 -12
  145. package/dist/src/components/layout/LayoutDialog.js +0 -12
  146. package/dist/src/components/layout/LayoutDialog.js.map +0 -1
  147. package/dist/src/components/layout/LayoutSnackbar.d.ts +0 -8
  148. package/dist/src/components/layout/LayoutSnackbar.js +0 -25
  149. package/dist/src/components/layout/LayoutSnackbar.js.map +0 -1
  150. package/dist/src/components/layout/NavigationDrawer.d.ts +0 -11
  151. package/dist/src/components/layout/NavigationDrawer.js +0 -70
  152. package/dist/src/components/layout/NavigationDrawer.js.map +0 -1
  153. package/dist/src/components/layout/NotificationMenu.d.ts +0 -8
  154. package/dist/src/components/layout/NotificationMenu.js +0 -26
  155. package/dist/src/components/layout/NotificationMenu.js.map +0 -1
  156. package/dist/src/components/layout/TypographyWithIcon.d.ts +0 -7
  157. package/dist/src/components/layout/TypographyWithIcon.js +0 -22
  158. package/dist/src/components/layout/TypographyWithIcon.js.map +0 -1
  159. package/dist/src/components/layout/Unauthorized.d.ts +0 -2
  160. package/dist/src/components/layout/Unauthorized.js +0 -26
  161. package/dist/src/components/layout/Unauthorized.js.map +0 -1
  162. package/dist/src/contexts/LayoutContext.d.ts +0 -40
  163. package/dist/src/contexts/LayoutContext.js +0 -60
  164. package/dist/src/contexts/LayoutContext.js.map +0 -1
  165. package/dist/src/contexts/UserContext.d.ts +0 -24
  166. package/dist/src/contexts/UserContext.js +0 -55
  167. package/dist/src/contexts/UserContext.js.map +0 -1
  168. package/dist/src/hooks/FormHooks.d.ts +0 -46
  169. package/dist/src/hooks/FormHooks.js +0 -31
  170. package/dist/src/hooks/FormHooks.js.map +0 -1
  171. package/dist/src/hooks/UseSnackbar.d.ts +0 -10
  172. package/dist/src/hooks/UseSnackbar.js +0 -23
  173. package/dist/src/hooks/UseSnackbar.js.map +0 -1
  174. package/dist/src/hooks/UseUser.d.ts +0 -10
  175. package/dist/src/hooks/UseUser.js +0 -25
  176. package/dist/src/hooks/UseUser.js.map +0 -1
  177. package/dist/src/index.d.ts +0 -20
  178. package/dist/src/index.js +0 -15
  179. package/dist/src/index.js.map +0 -1
  180. package/dist/src/models/Error.d.ts +0 -6
  181. package/dist/src/models/Error.js +0 -2
  182. package/dist/src/models/Error.js.map +0 -1
  183. package/dist/src/models/KeycloakSettings.d.ts +0 -8
  184. package/dist/src/models/KeycloakSettings.js +0 -2
  185. package/dist/src/models/KeycloakSettings.js.map +0 -1
  186. package/dist/src/models/LayoutPaletteColorOptions.d.ts +0 -6
  187. package/dist/src/models/LayoutPaletteColorOptions.js +0 -2
  188. package/dist/src/models/LayoutPaletteColorOptions.js.map +0 -1
  189. package/dist/src/models/LayoutRoute.d.ts +0 -14
  190. package/dist/src/models/LayoutRoute.js +0 -2
  191. package/dist/src/models/LayoutRoute.js.map +0 -1
  192. package/dist/src/models/Notification.d.ts +0 -9
  193. package/dist/src/models/Notification.js +0 -2
  194. package/dist/src/models/Notification.js.map +0 -1
  195. package/dist/src/models/PeoplesoftDepartment.d.ts +0 -14
  196. package/dist/src/models/PeoplesoftDepartment.js +0 -2
  197. package/dist/src/models/PeoplesoftDepartment.js.map +0 -1
  198. package/dist/src/models/PeoplesoftEmployee.d.ts +0 -34
  199. package/dist/src/models/PeoplesoftEmployee.js +0 -2
  200. package/dist/src/models/PeoplesoftEmployee.js.map +0 -1
  201. package/dist/src/models/Snackbar.d.ts +0 -15
  202. package/dist/src/models/Snackbar.js +0 -2
  203. package/dist/src/models/Snackbar.js.map +0 -1
  204. package/dist/src/models/User.d.ts +0 -27
  205. package/dist/src/models/User.js +0 -11
  206. package/dist/src/models/User.js.map +0 -1
  207. package/dist/src/models/types/EmployeeCategoryGroup.d.ts +0 -1
  208. package/dist/src/models/types/EmployeeCategoryGroup.js +0 -2
  209. package/dist/src/models/types/EmployeeCategoryGroup.js.map +0 -1
  210. package/dist/src/models/types/EmployeeStatus.d.ts +0 -1
  211. package/dist/src/models/types/EmployeeStatus.js +0 -2
  212. package/dist/src/models/types/EmployeeStatus.js.map +0 -1
  213. package/dist/src/utils/Auth.d.ts +0 -12
  214. package/dist/src/utils/Auth.js +0 -49
  215. package/dist/src/utils/Auth.js.map +0 -1
  216. package/dist/src/utils/Fetches.d.ts +0 -5
  217. package/dist/src/utils/Fetches.js +0 -66
  218. package/dist/src/utils/Fetches.js.map +0 -1
  219. package/dist/src/utils/FormUtils.d.ts +0 -7
  220. package/dist/src/utils/FormUtils.js +0 -9
  221. package/dist/src/utils/FormUtils.js.map +0 -1
  222. package/dist/src/utils/Helpers.d.ts +0 -11
  223. package/dist/src/utils/Helpers.js +0 -26
  224. package/dist/src/utils/Helpers.js.map +0 -1
  225. package/dist/tsconfig.tsbuildinfo +0 -1
  226. package/src/components/Layout.tsx +0 -183
  227. package/src/components/dataGrid/ChipInputCell.tsx +0 -31
  228. package/src/components/dataGrid/EditableColumnHeader.tsx +0 -7
  229. package/src/components/dataGrid/GridToolbar.tsx +0 -63
  230. package/src/components/dataGrid/TableContainer.tsx +0 -39
  231. package/src/components/form/FormAutocomplete.tsx +0 -34
  232. package/src/components/form/FormCheckbox.tsx +0 -32
  233. package/src/components/form/FormDatePicker.tsx +0 -34
  234. package/src/components/form/FormDateTimePicker.tsx +0 -34
  235. package/src/components/form/FormNumberField.tsx +0 -33
  236. package/src/components/form/FormRadioGroup.tsx +0 -43
  237. package/src/components/form/FormSlider.tsx +0 -28
  238. package/src/components/form/FormSubmitButton.tsx +0 -29
  239. package/src/components/form/FormSwitch.tsx +0 -32
  240. package/src/components/form/FormTextField.tsx +0 -26
  241. package/src/components/layout/AccountMenu.tsx +0 -160
  242. package/src/components/layout/DevelopmentBanner.tsx +0 -54
  243. package/src/components/layout/ErrorPage.tsx +0 -34
  244. package/src/components/layout/LayoutDialog.tsx +0 -50
  245. package/src/components/layout/LayoutSnackbar.tsx +0 -44
  246. package/src/components/layout/NavigationDrawer.tsx +0 -131
  247. package/src/components/layout/NotificationMenu.tsx +0 -76
  248. package/src/components/layout/TypographyWithIcon.tsx +0 -35
  249. package/src/components/layout/Unauthorized.tsx +0 -37
  250. package/src/contexts/LayoutContext.tsx +0 -127
  251. package/src/contexts/UserContext.tsx +0 -88
  252. package/src/hooks/FormHooks.ts +0 -33
  253. package/src/hooks/UseSnackbar.tsx +0 -28
  254. package/src/hooks/UseUser.tsx +0 -29
  255. package/src/index.ts +0 -27
  256. package/src/models/Error.tsx +0 -6
  257. package/src/models/KeycloakSettings.ts +0 -8
  258. package/src/models/LayoutPaletteColorOptions.tsx +0 -7
  259. package/src/models/LayoutRoute.ts +0 -15
  260. package/src/models/Notification.ts +0 -10
  261. package/src/models/PeoplesoftDepartment.ts +0 -15
  262. package/src/models/PeoplesoftEmployee.ts +0 -35
  263. package/src/models/Snackbar.ts +0 -16
  264. package/src/models/User.ts +0 -13
  265. package/src/models/types/EmployeeCategoryGroup.ts +0 -1
  266. package/src/models/types/EmployeeStatus.ts +0 -1
  267. package/src/utils/Auth.ts +0 -58
  268. package/src/utils/Fetches.ts +0 -83
  269. package/src/utils/FormUtils.ts +0 -22
  270. package/src/utils/Helpers.ts +0 -27
  271. package/tsconfig.json +0 -29
package/dist/vite.mjs ADDED
@@ -0,0 +1,182 @@
1
+ import z from "zod";
2
+ import axios from "axios";
3
+ import https from "node:https";
4
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+ import { loadEnv } from "vite";
7
+ //#region src/models/VaultConfig.ts
8
+ const VaultConfigSchema = z.object({
9
+ VAULT_ADDRESS: z.url(),
10
+ VAULT_USERNAME: z.string().min(1),
11
+ VAULT_PASSWORD: z.string().min(1),
12
+ VAULT_SECRET_PATH: z.string().min(1),
13
+ VAULT_MOUNT_POINT: z.string().default("release")
14
+ });
15
+ //#endregion
16
+ //#region src/lib/vite-plugin.ts
17
+ async function fetchVaultSecrets(env) {
18
+ const { VAULT_ADDRESS, VAULT_USERNAME, VAULT_PASSWORD, VAULT_SECRET_PATH, VAULT_MOUNT_POINT } = VaultConfigSchema.parse(env);
19
+ const client = axios.create({
20
+ baseURL: VAULT_ADDRESS,
21
+ httpsAgent: new https.Agent({ rejectUnauthorized: false })
22
+ });
23
+ const { data: loginData } = await client.post(`/v1/auth/userpass/login/${VAULT_USERNAME}`, { password: VAULT_PASSWORD });
24
+ const { data: secretData } = await client.get(`/v1/${VAULT_MOUNT_POINT}/data/${VAULT_SECRET_PATH}`, { headers: { "X-Vault-Token": loginData.auth.client_token } });
25
+ const secrets = secretData?.data?.data;
26
+ if (!secrets) throw new Error("No secrets found");
27
+ return Object.fromEntries(Object.entries(secrets).map(([key, value]) => [key, typeof value === "string" ? value : JSON.stringify(value)]));
28
+ }
29
+ async function loadVaultSecrets(command) {
30
+ if (command !== "serve") return;
31
+ const env = loadEnv("development", process.cwd(), "");
32
+ if (!env.VAULT_ADDRESS) return;
33
+ try {
34
+ const secrets = await fetchVaultSecrets(env);
35
+ Object.entries(secrets).forEach(([key, value]) => {
36
+ process.env[key] = env[key]?.trim() ? env[key] : value;
37
+ });
38
+ } catch (e) {
39
+ console.warn("[vite:wcz-layout] Vault failed:", e instanceof Error ? e.message : e);
40
+ }
41
+ }
42
+ function loadLocaleResources(localesPath, addWatchFile) {
43
+ if (!fs.existsSync(localesPath)) fs.mkdirSync(localesPath, { recursive: true });
44
+ const enPath = path.join(localesPath, "en.json");
45
+ if (!fs.existsSync(enPath)) fs.writeFileSync(enPath, JSON.stringify({}));
46
+ const files = fs.readdirSync(localesPath);
47
+ const resources = {};
48
+ for (const file of files.filter((f) => f.endsWith(".json"))) {
49
+ const lang = path.basename(file, ".json");
50
+ const filePath = path.join(localesPath, file);
51
+ try {
52
+ resources[lang] = { translation: JSON.parse(fs.readFileSync(filePath, "utf-8")) };
53
+ } catch {
54
+ resources[lang] = { translation: {} };
55
+ }
56
+ addWatchFile(filePath);
57
+ }
58
+ return resources;
59
+ }
60
+ function ensurePermissionsFile(permissionsPath, addWatchFile) {
61
+ const dir = path.dirname(permissionsPath);
62
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
63
+ if (!fs.existsSync(permissionsPath)) fs.writeFileSync(permissionsPath, "export const permissions = {\n admin: [\"wcz-developers\"]\n} as const;");
64
+ addWatchFile(permissionsPath);
65
+ }
66
+ function ensureScopesFile(scopesPath, addWatchFile) {
67
+ const dir = path.dirname(scopesPath);
68
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
69
+ if (!fs.existsSync(scopesPath)) fs.writeFileSync(scopesPath, "export const scopes = {\n} as const;");
70
+ addWatchFile(scopesPath);
71
+ }
72
+ function loadManifest(manifestPath, addWatchFile) {
73
+ addWatchFile(manifestPath);
74
+ try {
75
+ return JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
76
+ } catch {
77
+ return { name: "" };
78
+ }
79
+ }
80
+ function viteWczLayout() {
81
+ const virtualModuleId = "virtual:wcz-layout";
82
+ const resolvedVirtualModuleId = "\0virtual:wcz-layout";
83
+ let localesPath;
84
+ let permissionsPath;
85
+ let scopesPath;
86
+ let envPath;
87
+ let manifestPath;
88
+ return {
89
+ name: "vite:wcz-layout",
90
+ enforce: "pre",
91
+ configResolved(resolvedConfig) {
92
+ localesPath = path.resolve(resolvedConfig.root, "src/lib/locales");
93
+ permissionsPath = path.resolve(resolvedConfig.root, "src/lib/auth/permissions.ts");
94
+ scopesPath = path.resolve(resolvedConfig.root, "src/lib/auth/scopes.ts");
95
+ envPath = path.resolve(resolvedConfig.root, "src/env.ts");
96
+ manifestPath = path.resolve(resolvedConfig.root, "public/manifest.json");
97
+ },
98
+ async config(_, { command }) {
99
+ await loadVaultSecrets(command);
100
+ return {
101
+ optimizeDeps: {
102
+ exclude: [virtualModuleId],
103
+ include: [
104
+ "prop-types",
105
+ "react-is",
106
+ "hoist-non-react-statics",
107
+ "url-parse",
108
+ "attr-accept",
109
+ "@mui/x-date-pickers-pro",
110
+ "@mui/x-data-grid-premium"
111
+ ]
112
+ },
113
+ resolve: { dedupe: [
114
+ "react",
115
+ "react-dom",
116
+ "@mui/material",
117
+ "@mui/x-date-pickers",
118
+ "@mui/x-date-pickers-pro",
119
+ "@mui/x-data-grid",
120
+ "@mui/x-data-grid-premium",
121
+ "@emotion/react",
122
+ "@emotion/styled"
123
+ ] },
124
+ ssr: {
125
+ noExternal: [/@mui\//, /@emotion\//],
126
+ resolve: { conditions: [
127
+ "node",
128
+ "module",
129
+ "import"
130
+ ] }
131
+ }
132
+ };
133
+ },
134
+ configureServer(server) {
135
+ const refresh = (filePath) => {
136
+ if (filePath.includes(localesPath) || filePath === permissionsPath || filePath === scopesPath || filePath === envPath || filePath === manifestPath) {
137
+ const module = server.moduleGraph.getModuleById(resolvedVirtualModuleId);
138
+ if (module) server.moduleGraph.invalidateModule(module);
139
+ server.ws.send({
140
+ type: "full-reload",
141
+ path: "*"
142
+ });
143
+ }
144
+ };
145
+ server.watcher.add([
146
+ localesPath,
147
+ permissionsPath,
148
+ scopesPath,
149
+ envPath,
150
+ manifestPath
151
+ ]);
152
+ server.watcher.on("add", refresh);
153
+ server.watcher.on("change", refresh);
154
+ server.watcher.on("unlink", refresh);
155
+ },
156
+ resolveId(id) {
157
+ if (id === virtualModuleId) return resolvedVirtualModuleId;
158
+ return null;
159
+ },
160
+ load(id) {
161
+ if (id !== resolvedVirtualModuleId) return null;
162
+ const resources = loadLocaleResources(localesPath, this.addWatchFile.bind(this));
163
+ ensurePermissionsFile(permissionsPath, this.addWatchFile.bind(this));
164
+ ensureScopesFile(scopesPath, this.addWatchFile.bind(this));
165
+ const manifest = loadManifest(manifestPath, this.addWatchFile.bind(this));
166
+ const normalizedPermissionsPath = permissionsPath.split(path.sep).join(path.posix.sep);
167
+ const normalizedScopesPath = scopesPath.split(path.sep).join(path.posix.sep);
168
+ const normalizedEnvPath = envPath.split(path.sep).join(path.posix.sep);
169
+ return `
170
+ export const resources = ${JSON.stringify(resources)};
171
+ export const manifest = ${JSON.stringify(manifest)};
172
+ export { permissions } from "${normalizedPermissionsPath}";
173
+ export { scopes } from "${normalizedScopesPath}";
174
+ export { serverEnv } from "${normalizedEnvPath}";
175
+ `;
176
+ }
177
+ };
178
+ }
179
+ //#endregion
180
+ export { viteWczLayout };
181
+
182
+ //# sourceMappingURL=vite.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite.mjs","names":["z","VaultConfigSchema","object","VAULT_ADDRESS","url","VAULT_USERNAME","string","min","VAULT_PASSWORD","VAULT_SECRET_PATH","VAULT_MOUNT_POINT","default","VaultConfig","infer","fs","https","path","axios","loadEnv","VaultConfigSchema","Resource","Plugin","fetchVaultSecrets","env","Record","Promise","config","parse","VAULT_ADDRESS","VAULT_USERNAME","VAULT_PASSWORD","VAULT_SECRET_PATH","VAULT_MOUNT_POINT","client","create","baseURL","httpsAgent","Agent","rejectUnauthorized","data","loginData","post","password","secretData","get","headers","auth","client_token","secrets","Error","Object","fromEntries","entries","map","key","value","JSON","stringify","loadVaultSecrets","command","process","cwd","forEach","trim","e","console","warn","message","loadLocaleResources","localesPath","addWatchFile","existsSync","mkdirSync","recursive","enPath","join","writeFileSync","files","readdirSync","resources","file","filter","f","endsWith","lang","basename","filePath","translation","readFileSync","ensurePermissionsFile","permissionsPath","dir","dirname","ensureScopesFile","scopesPath","loadManifest","manifestPath","name","viteWczLayout","virtualModuleId","resolvedVirtualModuleId","envPath","enforce","configResolved","resolvedConfig","resolve","root","_","optimizeDeps","exclude","include","dedupe","ssr","noExternal","conditions","configureServer","server","refresh","includes","module","moduleGraph","getModuleById","invalidateModule","ws","send","type","watcher","add","on","resolveId","id","load","bind","manifest","normalizedPermissionsPath","split","sep","posix","normalizedScopesPath","normalizedEnvPath"],"sources":["../src/models/VaultConfig.ts","../src/lib/vite-plugin.ts"],"sourcesContent":["import z from \"zod\";\n\nexport const VaultConfigSchema = z.object({\n VAULT_ADDRESS: z.url(),\n VAULT_USERNAME: z.string().min(1),\n VAULT_PASSWORD: z.string().min(1),\n VAULT_SECRET_PATH: z.string().min(1),\n VAULT_MOUNT_POINT: z.string().default(\"release\"),\n});\n\nexport type VaultConfig = z.infer<typeof VaultConfigSchema>;\n","import fs from \"node:fs\";\nimport https from \"node:https\";\nimport path from \"node:path\";\nimport axios from \"axios\";\nimport { loadEnv } from \"vite\";\nimport { VaultConfigSchema } from \"../models/VaultConfig\";\nimport type { Resource } from \"i18next\";\nimport type { Plugin } from \"vite\";\n\nasync function fetchVaultSecrets(env: Record<string, string>): Promise<Record<string, string>> {\n const config = VaultConfigSchema.parse(env);\n const { VAULT_ADDRESS, VAULT_USERNAME, VAULT_PASSWORD, VAULT_SECRET_PATH, VAULT_MOUNT_POINT } =\n config;\n\n const client = axios.create({\n baseURL: VAULT_ADDRESS,\n httpsAgent: new https.Agent({ rejectUnauthorized: false }),\n });\n\n const { data: loginData } = await client.post(`/v1/auth/userpass/login/${VAULT_USERNAME}`, {\n password: VAULT_PASSWORD,\n });\n\n const { data: secretData } = await client.get(\n `/v1/${VAULT_MOUNT_POINT}/data/${VAULT_SECRET_PATH}`,\n {\n headers: { \"X-Vault-Token\": loginData.auth.client_token },\n },\n );\n\n const secrets = secretData?.data?.data;\n if (!secrets) throw new Error(\"No secrets found\");\n\n return Object.fromEntries(\n Object.entries(secrets).map(([key, value]) => [\n key,\n typeof value === \"string\" ? value : JSON.stringify(value),\n ]),\n );\n}\n\nasync function loadVaultSecrets(command: string): Promise<void> {\n if (command !== \"serve\") return;\n\n const env = loadEnv(\"development\", process.cwd(), \"\");\n if (!env.VAULT_ADDRESS) return;\n\n try {\n const secrets = await fetchVaultSecrets(env);\n Object.entries(secrets).forEach(([key, value]) => {\n process.env[key] = env[key]?.trim() ? env[key] : value;\n });\n } catch (e) {\n console.warn(\"[vite:wcz-layout] Vault failed:\", e instanceof Error ? e.message : e);\n }\n}\n\nfunction loadLocaleResources(localesPath: string, addWatchFile: (path: string) => void): Resource {\n if (!fs.existsSync(localesPath)) fs.mkdirSync(localesPath, { recursive: true });\n\n const enPath = path.join(localesPath, \"en.json\");\n if (!fs.existsSync(enPath)) fs.writeFileSync(enPath, JSON.stringify({}));\n\n const files = fs.readdirSync(localesPath);\n const resources: Resource = {};\n\n for (const file of files.filter((f) => f.endsWith(\".json\"))) {\n const lang = path.basename(file, \".json\");\n const filePath = path.join(localesPath, file);\n try {\n resources[lang] = { translation: JSON.parse(fs.readFileSync(filePath, \"utf-8\")) };\n } catch {\n resources[lang] = { translation: {} };\n }\n addWatchFile(filePath);\n }\n\n return resources;\n}\n\nfunction ensurePermissionsFile(\n permissionsPath: string,\n addWatchFile: (path: string) => void,\n): void {\n const dir = path.dirname(permissionsPath);\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n if (!fs.existsSync(permissionsPath)) {\n fs.writeFileSync(\n permissionsPath,\n 'export const permissions = {\\n admin: [\"wcz-developers\"]\\n} as const;',\n );\n }\n addWatchFile(permissionsPath);\n}\n\nfunction ensureScopesFile(scopesPath: string, addWatchFile: (path: string) => void): void {\n const dir = path.dirname(scopesPath);\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n if (!fs.existsSync(scopesPath)) {\n fs.writeFileSync(scopesPath, \"export const scopes = {\\n} as const;\");\n }\n addWatchFile(scopesPath);\n}\n\nfunction loadManifest(\n manifestPath: string,\n addWatchFile: (path: string) => void,\n): { name: string } & Record<string, unknown> {\n addWatchFile(manifestPath);\n try {\n return JSON.parse(fs.readFileSync(manifestPath, \"utf-8\"));\n } catch {\n return { name: \"\" };\n }\n}\n\nexport function viteWczLayout(): Plugin {\n const virtualModuleId = \"virtual:wcz-layout\";\n const resolvedVirtualModuleId = \"\\0\" + virtualModuleId;\n\n let localesPath: string;\n let permissionsPath: string;\n let scopesPath: string;\n let envPath: string;\n let manifestPath: string;\n\n return {\n name: \"vite:wcz-layout\",\n enforce: \"pre\",\n configResolved(resolvedConfig) {\n localesPath = path.resolve(resolvedConfig.root, \"src/lib/locales\");\n permissionsPath = path.resolve(resolvedConfig.root, \"src/lib/auth/permissions.ts\");\n scopesPath = path.resolve(resolvedConfig.root, \"src/lib/auth/scopes.ts\");\n envPath = path.resolve(resolvedConfig.root, \"src/env.ts\");\n manifestPath = path.resolve(resolvedConfig.root, \"public/manifest.json\");\n },\n async config(_, { command }) {\n await loadVaultSecrets(command);\n\n return {\n optimizeDeps: {\n exclude: [virtualModuleId],\n include: [\n // CJS deps reached through @mui/* and @emotion/* imports in our dist\n \"prop-types\",\n \"react-is\",\n \"hoist-non-react-statics\",\n // CJS dep of tus-js-client (file upload server fn)\n \"url-parse\",\n // CJS dep of react-dropzone\n \"attr-accept\",\n \"@mui/x-date-pickers-pro\",\n \"@mui/x-data-grid-premium\",\n ],\n },\n resolve: {\n dedupe: [\n \"react\",\n \"react-dom\",\n \"@mui/material\",\n \"@mui/x-date-pickers\",\n \"@mui/x-date-pickers-pro\",\n \"@mui/x-data-grid\",\n \"@mui/x-data-grid-premium\",\n \"@emotion/react\",\n \"@emotion/styled\",\n ],\n },\n ssr: {\n noExternal: [/@mui\\//, /@emotion\\//],\n resolve: {\n conditions: [\"node\", \"module\", \"import\"],\n },\n },\n };\n },\n configureServer(server) {\n const refresh = (filePath: string) => {\n if (\n filePath.includes(localesPath) ||\n filePath === permissionsPath ||\n filePath === scopesPath ||\n filePath === envPath ||\n filePath === manifestPath\n ) {\n const module = server.moduleGraph.getModuleById(resolvedVirtualModuleId);\n if (module) server.moduleGraph.invalidateModule(module);\n server.ws.send({ type: \"full-reload\", path: \"*\" });\n }\n };\n\n server.watcher.add([localesPath, permissionsPath, scopesPath, envPath, manifestPath]);\n server.watcher.on(\"add\", refresh);\n server.watcher.on(\"change\", refresh);\n server.watcher.on(\"unlink\", refresh);\n },\n resolveId(id) {\n if (id === virtualModuleId) return resolvedVirtualModuleId;\n return null;\n },\n load(id) {\n if (id !== resolvedVirtualModuleId) return null;\n\n const resources = loadLocaleResources(localesPath, this.addWatchFile.bind(this));\n ensurePermissionsFile(permissionsPath, this.addWatchFile.bind(this));\n ensureScopesFile(scopesPath, this.addWatchFile.bind(this));\n const manifest = loadManifest(manifestPath, this.addWatchFile.bind(this));\n\n const normalizedPermissionsPath = permissionsPath.split(path.sep).join(path.posix.sep);\n const normalizedScopesPath = scopesPath.split(path.sep).join(path.posix.sep);\n const normalizedEnvPath = envPath.split(path.sep).join(path.posix.sep);\n return `\n export const resources = ${JSON.stringify(resources)};\n export const manifest = ${JSON.stringify(manifest)};\n export { permissions } from \"${normalizedPermissionsPath}\";\n export { scopes } from \"${normalizedScopesPath}\";\n export { serverEnv } from \"${normalizedEnvPath}\";\n `;\n },\n };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,62 +1,129 @@
1
- {
2
- "name": "wcz-layout",
3
- "license": "MIT",
4
- "author": "Dalibor Homola",
5
- "version": "6.7.2",
6
- "types": "dist/src/index.d.ts",
7
- "main": "dist/src/index.js",
8
- "module": "dist/src/index.js",
9
- "exports": {
10
- ".": {
11
- "types": "./dist/src/index.d.ts",
12
- "import": "./dist/src/index.js",
13
- "default": "./dist/src/index.js"
14
- }
15
- },
16
- "scripts": {
17
- "npm-install": "npm install",
18
- "npm-update": "npm update",
19
- "analyze": "cem analyze --litelement",
20
- "start": "tsc && concurrently -k -r \"tsc --watch --preserveWatchOutput\" \"wds\"",
21
- "build": "tsc && npm run analyze -- --exclude dist",
22
- "prepublish": "tsc && npm run analyze -- --exclude dist",
23
- "publish": "npm publish --tag legacy"
24
- },
25
- "dependencies": {
26
- "@azure/msal-browser": "^4.27.0",
27
- "@azure/msal-react": "^3.0.23",
28
- "uuidv7": "^1.0.1",
29
- "axios": "^1.13.2",
30
- "i18next": "^24.2.1",
31
- "i18next-browser-languagedetector": "^8.0.2",
32
- "i18next-http-backend": "^3.0.1",
33
- "react-i18next": "^15.0.1",
34
- "react-number-format": "^5.4.4",
35
- "use-local-storage-state": "^19.4.0",
36
- "zod-i18n-map": "^2.27.0"
37
- },
38
- "devDependencies": {
39
- "@custom-elements-manifest/analyzer": "^0.4.17",
40
- "@web/dev-server": "^0.1.28",
41
- "concurrently": "^5.3.0",
42
- "lit": "^2.0.2",
43
- "tslib": "^2.7.0",
44
- "typescript": "^5.5.4"
45
- },
46
- "peerDependencies": {
47
- "@emotion/react": "11.x",
48
- "@emotion/styled": "11.x",
49
- "@mui/icons-material": "6.x",
50
- "@mui/material": "6.x",
51
- "@mui/x-data-grid-premium": "7.x",
52
- "@mui/x-date-pickers-pro": "7.x",
53
- "@tanstack/react-query": "5.x",
54
- "@tanstack/react-form": "1.x",
55
- "moment": "2.x",
56
- "react": "18.x || 19.x",
57
- "react-dom": "18.x || 19.x",
58
- "react-router-dom": "6.x || 7.x",
59
- "zod": "3.x"
60
- },
61
- "customElements": "custom-elements.json"
62
- }
1
+ {
2
+ "name": "wcz-layout",
3
+ "version": "9.4.2",
4
+ "private": false,
5
+ "keywords": [
6
+ "tanstack-intent"
7
+ ],
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://gitlab.wistron.com/wcz/it-developers/layout/tanstack.git"
11
+ },
12
+ "files": [
13
+ "dist",
14
+ "skills",
15
+ "!skills/_artifacts"
16
+ ],
17
+ "type": "module",
18
+ "sideEffects": [
19
+ "./dist/hooks.mjs"
20
+ ],
21
+ "types": "./dist/index.d.mts",
22
+ "exports": {
23
+ "./package.json": "./package.json",
24
+ ".": {
25
+ "types": "./dist/index.d.mts",
26
+ "import": "./dist/index.mjs"
27
+ },
28
+ "./components": {
29
+ "types": "./dist/components.d.mts",
30
+ "import": "./dist/components.mjs"
31
+ },
32
+ "./hooks": {
33
+ "types": "./dist/hooks.d.mts",
34
+ "import": "./dist/hooks.mjs"
35
+ },
36
+ "./middleware": {
37
+ "types": "./dist/middleware.d.mts",
38
+ "import": "./dist/middleware.mjs"
39
+ },
40
+ "./models": {
41
+ "types": "./dist/models.d.mts",
42
+ "import": "./dist/models.mjs"
43
+ },
44
+ "./data/client": {
45
+ "types": "./dist/data/client.d.mts",
46
+ "import": "./dist/data/client.mjs"
47
+ },
48
+ "./data/server": {
49
+ "types": "./dist/data/server.d.mts",
50
+ "import": "./dist/data/server.mjs"
51
+ },
52
+ "./utils": {
53
+ "types": "./dist/utils.d.mts",
54
+ "import": "./dist/utils.mjs"
55
+ },
56
+ "./auth": {
57
+ "types": "./dist/auth.d.mts",
58
+ "import": "./dist/auth.mjs"
59
+ },
60
+ "./vite": {
61
+ "types": "./dist/vite.d.mts",
62
+ "import": "./dist/vite.mjs"
63
+ }
64
+ },
65
+ "scripts": {
66
+ "dev": "vp dev",
67
+ "vp:install": "vp install",
68
+ "vp:update": "vp update",
69
+ "ncu:install": "npx npm-check-updates -i",
70
+ "lint:package": "publint",
71
+ "build": "vp pack",
72
+ "prepublishOnly": "npm run build"
73
+ },
74
+ "dependencies": {
75
+ "@azure/msal-node": "^5.4.0",
76
+ "@t3-oss/env-core": "^0.13.11",
77
+ "i18next": "^26.3.5",
78
+ "i18next-browser-languagedetector": "^8.2.1",
79
+ "jose": "^6.2.3",
80
+ "react-dropzone": "^15.0.0",
81
+ "react-i18next": "^17.0.8",
82
+ "react-intersection-observer": "^10.0.3",
83
+ "react-number-format": "^5.4.5",
84
+ "tus-js-client": "^4.3.1",
85
+ "uuidv7": "^1.2.1"
86
+ },
87
+ "devDependencies": {
88
+ "@rolldown/plugin-babel": "^0.2.3",
89
+ "@tanstack/ai": "^0.40.0",
90
+ "@tanstack/ai-client": "^0.20.0",
91
+ "@tanstack/ai-openai": "^0.16.0",
92
+ "@types/node": "^24.10.13",
93
+ "@types/react": "^19.2.17",
94
+ "@types/react-dom": "^19.2.3",
95
+ "@vitejs/plugin-react": "^6.0.3",
96
+ "babel-plugin-react-compiler": "^1.0.0",
97
+ "nitro": "npm:nitro-nightly@latest",
98
+ "publint": "^0.3.21",
99
+ "typescript": "^6.0.3",
100
+ "vite-plugin-checker": "0.14.1"
101
+ },
102
+ "peerDependencies": {
103
+ "@emotion/cache": "11.x",
104
+ "@emotion/react": "11.x",
105
+ "@emotion/styled": "11.x",
106
+ "@mui/icons-material": "9.x",
107
+ "@mui/material": "9.x",
108
+ "@mui/x-data-grid-premium": "9.x",
109
+ "@mui/x-date-pickers-pro": "9.x",
110
+ "@tanstack/query-db-collection": "1.x",
111
+ "@tanstack/react-db": "0.x",
112
+ "@tanstack/react-form": "1.x",
113
+ "@tanstack/react-query": "5.x",
114
+ "@tanstack/react-router": "1.x",
115
+ "@tanstack/react-router-ssr-query": "1.x",
116
+ "@tanstack/react-start": "1.x",
117
+ "axios": "1.x",
118
+ "dayjs": "1.x",
119
+ "react": "19.x",
120
+ "react-dom": "19.x",
121
+ "vite": "npm:@voidzero-dev/vite-plus-core@latest",
122
+ "vite-plus": "latest",
123
+ "zod": "4.x"
124
+ },
125
+ "overrides": {
126
+ "vite": "npm:@voidzero-dev/vite-plus-core@latest"
127
+ },
128
+ "packageManager": "npm@12.0.0"
129
+ }
@@ -0,0 +1,93 @@
1
+ ---
2
+ name: client-db
3
+ description: "Use when: creating or modifying TanStack DB collections, live queries, optimistic collection writes, subset loading, collection preloading."
4
+ ---
5
+
6
+ ## Rules
7
+
8
+ - Use `eager` syncMode for top-level collections, `on-demand` for child/relational data.
9
+ - Use `useLiveQuery` for list/grid pages and `useLiveSuspenseQuery` for detail components wrapped in suspense.
10
+ - For mutations use `createOptimisticAction` — mirror the server mutation in `onMutate`, then call the server function and `collection.utils.refetch()` in `mutationFn`.
11
+ - Use `meta.loadSubsetOptions` for relational subset loading.
12
+
13
+ ## File Placement
14
+
15
+ ```
16
+ src/db-collections/ — DB collections
17
+ src/server/actions/ — server functions (select/update/insert/delete)
18
+ src/lib/schemas/ — Zod schemas (shared between client and server)
19
+ src/lib/auth/scopes.ts — API scope keys
20
+ ```
21
+
22
+ ## Examples
23
+
24
+ ```ts
25
+ // src/db-collections/<feature>.ts
26
+ export const librariesCollection = createCollection(
27
+ queryCollectionOptions({
28
+ queryKey: ["libraries"],
29
+ queryFn: () => selectLibraries(),
30
+ getKey: ({ id }) => id,
31
+ schema: LibrarySchema,
32
+ queryClient: queryClient,
33
+ syncMode: "eager",
34
+ }),
35
+ );
36
+
37
+ // src/db-collections/<feature>.ts
38
+ export const bookCollection = createCollection(
39
+ queryCollectionOptions({
40
+ queryKey: ["books"],
41
+ queryFn: ({ meta }) => selectBooks({ data: meta?.loadSubsetOptions }),
42
+ getKey: ({ id }) => id,
43
+ schema: BookSchema,
44
+ queryClient: queryClient,
45
+ syncMode: "on-demand",
46
+ }),
47
+ );
48
+
49
+ // simple query
50
+ const { data, isLoading } = useLiveQuery((q) =>
51
+ q.from({ library: libraryCollection }).orderBy(({ library }) => library.name, "asc"),
52
+ );
53
+
54
+ // advanced query with relational data
55
+ const { data } = useLiveQuery((q) =>
56
+ q
57
+ .from({ library: libraryCollection })
58
+ .where(({ library }) => eq(library.id, id))
59
+ .findOne()
60
+ .select(({ library }) => ({
61
+ ...library,
62
+ books: toArray(
63
+ q
64
+ .from({ book: bookCollection })
65
+ .where(({ book }) => eq(book.libraryId, library.id))
66
+ .orderBy(({ book }) => book.title, "asc")
67
+ .select(({ book }) => ({
68
+ id: book.id,
69
+ title: book.title,
70
+ })),
71
+ ),
72
+ })),
73
+ );
74
+
75
+ // form submission handler
76
+ const handleOnSubmit = createOptimisticAction<Library>({
77
+ onMutate: (formValues) => {
78
+ libraryCollection.update(id, (prev) => Object.assign(prev, formValues));
79
+ },
80
+ mutationFn: async (formValues) => {
81
+ await updateLibrary({ data: formValues });
82
+ await libraryCollection.utils.refetch();
83
+ },
84
+ });
85
+
86
+ // calling the handler
87
+ try {
88
+ const transaction = handleOnSubmit(formValues);
89
+ await transaction.isPersisted.promise;
90
+ } catch (error) {
91
+ if (error instanceof Error) alert(error.message);
92
+ }
93
+ ```
@@ -0,0 +1,142 @@
1
+ ---
2
+ name: data-grid
3
+ description: "Use when: building or configuring MUI X DataGrid tables, editable columns, toolbar actions, row selection, or TanStack DB-backed grids."
4
+ ---
5
+
6
+ ## Rules
7
+
8
+ - Wrap DataGrid in `Fullscreen` when it is the only content on the page.
9
+ - Type columns as `Array<GridColDef<RowType>>` with the row interface.
10
+ - Use translation for all `headerName` values.
11
+ - Use `rows`, `columns`, `showToolbar`, `loading`, `ignoreDiacritics`, `cellSelection`, and `disableRowSelectionOnClick` on grids.
12
+ - For enums use `type: "singleSelect"` with `{ value, label }` options array used from enumObject.
13
+ - For editable columns, pair `editable: true` with `renderHeader: EditableColumnHeader`.
14
+ - Use `EditableColumnHeader`, and router button/grid action components from `wcz-layout/components` when they fit.
15
+ - Always set `valueFormatter: (value) => dayjs(value).format("L LT")` for columns type `dateTime` or `format("L")` for columns type `date`.
16
+
17
+ ## File Placement
18
+
19
+ ```
20
+ @mui/x-data-grid-premium — GridColDef, DataGridPremium
21
+ src/db-collections/ - TanStack DB collections to get data
22
+ @tanstack/react-db - useLiveQuery, useLiveSuspenseQuery
23
+ src/server/actions/ - server functions and enums
24
+ wcz-layout/components - EditableColumnHeader, Fullscreen
25
+ wcz-layout/hooks - useTranslation
26
+ ```
27
+
28
+ ## Examples
29
+
30
+ ```tsx
31
+ // src/routes/<feature>s/index.tsx
32
+ const { t } = useTranslation();
33
+ const { confirm, alert } = useDialogs();
34
+ const navigate = useNavigate();
35
+ const [cellSelectionModel, setCellSelectionModel] = useState<GridCellSelectionModel>({});
36
+
37
+ const { data, isLoading } = useLiveQuery((q) =>
38
+ q.from({ feature: featureCollection }).orderBy(({ feature }) => feature.name, "asc"),
39
+ );
40
+
41
+ const columns: Array<GridColDef<Feature>> = [
42
+ {
43
+ field: "name",
44
+ headerName: t("Feature.Name"),
45
+ width: 200,
46
+ editable: true,
47
+ renderHeader: EditableColumnHeader,
48
+ },
49
+ {
50
+ field: "status",
51
+ headerName: t("Feature.Status"),
52
+ width: 200,
53
+ type: "singleSelect",
54
+ valueOptions: featureStatusEnum.enumValues.map((status) => ({
55
+ value: status,
56
+ label: t(`FeatureStatus.${status}`),
57
+ })),
58
+ },
59
+ ];
60
+
61
+ const handleOnDelete = createOptimisticAction<Array<string>>({
62
+ onMutate: (ids) => {
63
+ ids.forEach((id) => {
64
+ featureCollection.delete(id);
65
+ });
66
+ },
67
+ mutationFn: async (ids) => {
68
+ deleteFeatures({ data: ids });
69
+ await featureCollection.utils.refetch();
70
+ },
71
+ });
72
+
73
+ return (
74
+ <Fullscreen>
75
+ <DataGridPremium
76
+ rows={data}
77
+ columns={columns}
78
+ showToolbar
79
+ loading={isLoading}
80
+ ignoreDiacritics
81
+ onRowDoubleClick={({ row }) => navigate({ to: "/features/$id", params: { id: row.id } })}
82
+ cellSelection
83
+ disableRowSelectionOnClick
84
+ cellSelectionModel={cellSelectionModel}
85
+ onCellSelectionModelChange={(newModel) => setCellSelectionModel(newModel)}
86
+ slots={{ toolbar: DataGridToolbar }}
87
+ slotProps={{
88
+ toolbar: {
89
+ title: t("Feature.Features"),
90
+ actions: [
91
+ <Tooltip key="create" title={t("Create")}>
92
+ <RouterIconButton to="/features/create">
93
+ <Add fontSize="small" />
94
+ </RouterIconButton>
95
+ </Tooltip>,
96
+ Object.keys(cellSelectionModel).length === 1 && (
97
+ <Tooltip key="edit" title={t("Edit")}>
98
+ <RouterIconButton
99
+ to="/features/edit/$id"
100
+ params={{ id: Object.keys(cellSelectionModel)[0].toString() }}
101
+ >
102
+ <Edit fontSize="small" />
103
+ </RouterIconButton>
104
+ </Tooltip>
105
+ ),
106
+ Object.keys(cellSelectionModel).length > 0 && (
107
+ <Tooltip key="delete" title={t("Delete")}>
108
+ <IconButton
109
+ onClick={async () => {
110
+ const confirmed = await confirm(
111
+ t("DeleteConfirmation", { count: Object.keys(cellSelectionModel).length }),
112
+ );
113
+ if (confirmed) {
114
+ try {
115
+ const transaction = handleOnDelete(
116
+ Object.keys(cellSelectionModel).map((id) => id.toString()),
117
+ );
118
+ await transaction.isPersisted.promise;
119
+ setCellSelectionModel({});
120
+ } catch (error) {
121
+ if (error instanceof Error) await alert(error.message);
122
+ }
123
+ }
124
+ }}
125
+ >
126
+ <Badge
127
+ badgeContent={Object.keys(cellSelectionModel).length}
128
+ invisible={Object.keys(cellSelectionModel).length <= 1}
129
+ color="error"
130
+ >
131
+ <Delete fontSize="small" />
132
+ </Badge>
133
+ </IconButton>
134
+ </Tooltip>
135
+ ),
136
+ ],
137
+ },
138
+ }}
139
+ />
140
+ </Fullscreen>
141
+ );
142
+ ```