wcz-layout 6.7.2 → 9.4.1

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 +1940 -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 +107 -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 +29 -0
  77. package/skills/services/docs/approval.md +256 -0
  78. package/skills/services/docs/email.md +32 -0
  79. package/skills/services/docs/file.md +83 -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 +37 -0
  86. package/skills/start/steps/05-entra-setup.md +59 -0
  87. package/skills/start/steps/06-vault-setup.md +50 -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.1",
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,107 @@
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
+ - Use Axios with auth interceptor `getAccessToken` but only for public REST APIs; use default `api` as a scope key.
13
+
14
+ ## File Placement
15
+
16
+ ```
17
+ src/db-collections/ — DB collections
18
+ src/server/actions/ — server functions (select/update/insert/delete)
19
+ src/lib/schemas/ — Zod schemas (shared between client and server)
20
+ src/lib/auth/scopes.ts — API scope keys
21
+ wcz-layout/data — queryClient instance
22
+ wcz-layout/auth — getAccessToken utility function
23
+ ```
24
+
25
+ ## Examples
26
+
27
+ ```ts
28
+ // src/db-collections/<feature>.ts
29
+ export const api = axios.create({
30
+ baseURL: "/api/libraries",
31
+ });
32
+
33
+ api.interceptors.request.use(async (config) => {
34
+ const accessToken = await getAccessToken("api");
35
+ config.headers.set("Authorization", `Bearer ${accessToken}`);
36
+ return config;
37
+ });
38
+
39
+ // src/db-collections/<feature>.ts
40
+ export const librariesCollection = createCollection(
41
+ queryCollectionOptions({
42
+ queryKey: ["libraries"],
43
+ queryFn: () => selectLibraries(),
44
+ getKey: ({ id }) => id,
45
+ schema: LibrarySchema,
46
+ queryClient: queryClient,
47
+ syncMode: "eager",
48
+ }),
49
+ );
50
+
51
+ // src/db-collections/<feature>.ts
52
+ export const bookCollection = createCollection(
53
+ queryCollectionOptions({
54
+ queryKey: ["books"],
55
+ queryFn: ({ meta }) => selectBooks({ data: meta?.loadSubsetOptions }),
56
+ getKey: ({ id }) => id,
57
+ schema: BookSchema,
58
+ queryClient: queryClient,
59
+ syncMode: "on-demand",
60
+ }),
61
+ );
62
+
63
+ // simple query
64
+ const { data, isLoading } = useLiveQuery((q) =>
65
+ q.from({ library: libraryCollection }).orderBy(({ library }) => library.name, "asc"),
66
+ );
67
+
68
+ // advanced query with relational data
69
+ const { data } = useLiveQuery((q) =>
70
+ q
71
+ .from({ library: libraryCollection })
72
+ .where(({ library }) => eq(library.id, id))
73
+ .findOne()
74
+ .select(({ library }) => ({
75
+ ...library,
76
+ books: toArray(
77
+ q
78
+ .from({ book: bookCollection })
79
+ .where(({ book }) => eq(book.libraryId, library.id))
80
+ .orderBy(({ book }) => book.title, "asc")
81
+ .select(({ book }) => ({
82
+ id: book.id,
83
+ title: book.title,
84
+ })),
85
+ ),
86
+ })),
87
+ );
88
+
89
+ // form submission handler
90
+ const handleOnSubmit = createOptimisticAction<Library>({
91
+ onMutate: (formValues) => {
92
+ libraryCollection.update(id, (prev) => Object.assign(prev, formValues));
93
+ },
94
+ mutationFn: async (formValues) => {
95
+ await updateLibrary({ data: formValues });
96
+ await libraryCollection.utils.refetch();
97
+ },
98
+ });
99
+
100
+ // calling the handler
101
+ try {
102
+ const transaction = handleOnSubmit(formValues);
103
+ await transaction.isPersisted.promise;
104
+ } catch (error) {
105
+ if (error instanceof Error) alert(error.message);
106
+ }
107
+ ```
@@ -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
+ ```