mui 6

Massimo Melina committed Mar 14, 2026 at 18:13 UTC d61966867cb011ef7495f1cce026794934ac37df
22 files changed +817 -537
admin/package.json
+6 -6
@@ -12,12 +12,12 @@
12 "@hfs/mui-grid-form": "*",
13 "@hfs/shared": "*",
14 "@emotion/styled": "^11.11.5",
15 - "@mui/icons-material": "^5.18.0",
16 - "@mui/lab": "^5.0.0-alpha.177",
17 - "@mui/material": "^5.18.0",
18 - "@mui/x-data-grid": "^6.20.4",
19 - "@mui/x-date-pickers": "^6.20.2",
20 - "@mui/x-tree-view": "^6.17.0",
15 + "@mui/icons-material": "^6.4.11",
16 + "@mui/lab": "^6.0.1-beta.34",
17 + "@mui/material": "^6.4.11",
18 + "@mui/x-data-grid": "^7.29.0",
19 + "@mui/x-date-pickers": "^7.29.0",
20 + "@mui/x-tree-view": "^7.29.0",
21 "@gregoranders/csv": "^0.0.13",
22 "dayjs": "^1.11.10",
23 "prismjs": "^1.29.0",
admin/src/AccountForm.ts
+1 -1
@@ -69,7 +69,7 @@ export default function AccountForm({ account, done, groups, addToBar, reload }:
69
70 { k: 'disabled', comp: BoolField, fromField: x=>!x, toField: x=>!x, label: "Enabled", xs: 12, sm: 6, lg: 4,
71 helperText: values.disabled || values.canLogin !== false ? "Login is prevented if account is disabled, or all its groups are disabled"
72 - : h(Box, { color: 'warning.main', component: 'span' },
72 + : h(Box, { color: 'warning.main', component: 'span' } as any, // Box.component has ts problems with h()
73 new Date(account.expire!) < new Date() ? "Login is prevented because account is expired" // use account instead of values, so to use the value currently applied
74 : "Login is prevented because all of its groups are disabled")
75 },
admin/src/AccountsPage.ts
+20 -14
@@ -8,7 +8,7 @@ import {
8 } from '@mui/icons-material'
9 import { newDialog, with_, md, Jsonify } from './misc'
10 import { Btn, Flex, IconBtn, iconTooltip, reloadBtn, useBreakpoint, useToggleButton } from './mui'
11 -import { TreeItem, TreeView } from '@mui/x-tree-view'
11 +import { TreeItem, SimpleTreeView } from '@mui/x-tree-view'
12 import MenuButton from './MenuButton'
13 import AccountForm from './AccountForm'
14 import _ from 'lodash'
@@ -19,6 +19,9 @@ import apiAccounts from '../../src/api.accounts'
19
20 export type Account = Jsonify<ReturnType<typeof apiAccounts.get_accounts>['list'][0]>
21
22 +const SEP = '\t'
23 +const userFromItemId = (itemId?: string) => itemId?.split(SEP).at(-1)
24 +
25 export default function AccountsPage() {
26 const { username, accountsAsTree } = useSnapState()
27 const { data, reload, element } = useApiEx<typeof apiAccounts.get_accounts>('get_accounts')
@@ -26,10 +29,10 @@ export default function AccountsPage() {
29 const selectionMode = Array.isArray(sel)
30 useEffect(() => { // if accounts are reloaded, review the selection to remove elements that don't exist anymore
31 if (Array.isArray(data?.list) && selectionMode)
29 - setSel( sel.filter(u => data!.list.find((e:any) => e?.username === u)) ) // remove elements that don't exist anymore
32 + setSel( sel.filter(x => data!.list.find((e:any) => e?.username === userFromItemId(x))) ) // remove elements that don't exist anymore
33 }, [data]) //eslint-disable-line -- Don't fall for its suggestion to add `sel` here: we modify it and declaring it as a dependency would cause a logical loop
34 const list = useMemo(() => data && _.sortBy(data.list, [x => !x.isGroup, x => !x.adminActualAccess, 'username']), [data])
32 - const selectedAccount = selectionMode && _.find(list, { username: sel[0] })
35 + const selectedAccount = selectionMode && _.find(list, { username: userFromItemId(sel[0]) })
36 const sideBreakpoint = 'md'
37 const isSideBreakpoint = useBreakpoint(sideBreakpoint)
38
@@ -40,7 +43,7 @@ export default function AccountsPage() {
43 h(Btn, { onClick: deleteAccounts, icon: Delete }, "Remove"),
44 ),
45 h(List, {},
43 - sel.map(username =>
46 + _.uniq(sel.map(userFromItemId)).map(username =>
47 h(ListItem, { key: username },
48 h(ListItemText, {}, username))))
49 )
@@ -107,22 +110,24 @@ export default function AccountsPage() {
110 list?.length! > 0 && h(Typography, { p: 1 }, `${list!.length} account(s)`),
111 ),
112 !list?.length && h(Alert, { severity: 'info' }, md`To access administration <u>remotely</u> you will need to create a user account with admin permission`),
110 - h(TreeView<true>, { // true because it's not detecting multiSelect correctly (ts495)
113 + h(SimpleTreeView<true>, { // true because it's not detecting multiSelect correctly (ts495)
114 multiSelect: true,
115 sx: { pr: 4, pb: 2, minWidth: '15em' },
113 - selected: selectionMode ? sel : [],
114 - defaultCollapseIcon: h(ExpandMore),
115 - defaultExpandIcon: h(ChevronRight),
116 - onNodeSelect(ev, ids) {
117 - if (!(ev.target as any)?.closest?.('.MuiTreeItem-iconContainer')) // don't select if clicked the expansion button, mostly for mobile users
116 + selectedItems: selectionMode ? sel : [],
117 + slots: {
118 + collapseIcon: ExpandMore,
119 + expandIcon: ChevronRight,
120 + },
121 + onSelectedItemsChange(ev, ids) {
122 + if (!(ev?.target as any)?.closest?.('.MuiTreeItem-iconContainer')) // don't select if clicked the expansion button, mostly for mobile users
123 setSel(ids)
124 }
125 },
121 - list && (function recur(thisLevel): ReactNode {
126 + list && (function recur(thisLevel, prefixPath=''): ReactNode {
127 return thisLevel.map(ac =>
128 h(TreeItem, {
129 key: ac.username,
125 - nodeId: ac.username,
130 + itemId: prefixPath + ac.username,
131 label: h(Box, {
132 sx: {
133 display: 'flex',
@@ -141,7 +146,7 @@ export default function AccountsPage() {
146 Boolean(ac.belongs?.length) && h(Box, { sx: { color: 'text.secondary', fontSize: 'small' } },
147 '(', ac.belongs?.join(', '), ')')
148 ),
144 - }, showTree && recur(list.filter(x => ac.directMembers?.includes(x.username)))))
149 + }, showTree && recur(list.filter(x => ac.directMembers?.includes(x.username)), prefixPath+ac.username+SEP)))
150 })(showTree ? list.filter(ac => !list.some(x => x.members?.includes(ac.username))) : list)
151 )
152 ),
@@ -169,7 +174,8 @@ export default function AccountsPage() {
174 }
175
176 async function deleteAccounts() {
172 - const toDelete = _.without(sel, username)
177 + if (typeof sel === 'string') return
178 + const toDelete = _.without(_.uniq(sel.map(userFromItemId)), username)
179 if (sel.length > toDelete.length)
180 if (!await confirmDialog(`You cannot ask to delete the account you are using. Continue with the rest?`)) return
181 if (!toDelete.length)
admin/src/App.ts
+3 -3
@@ -101,7 +101,7 @@ function Routed() {
101 })),
102 h(Box, { display: 'flex', flex: 1, }, // horizontal layout for menu-content
103 sideMenu && h(MainMenu, { itemTitle, onSelect(){} }),
104 - h(Box, {
104 + h(Box as any, {
105 component: 'main',
106 sx: {
107 background: 'url(cup.svg) no-repeat right fixed',
@@ -156,11 +156,11 @@ function StickyBar({ title, titleSide, openMenu, props }: { props?: BoxProps, ti
156 '& .MuiAlert-message': { py: '1px' }
157 }
158 },
159 - h(Box, { component: 'h2', m: 0, whiteSpace: 'nowrap' }, title),
159 + h(Box as any, { component: 'h2', m: 0, whiteSpace: 'nowrap' }, title),
160 titleSide
161 ),
162 )
163 )
164 }
165
166 -export default App
\ No newline at end of file
166 +export default App
admin/src/ArrayField.ts
+2 -4
@@ -82,9 +82,7 @@ export function ArrayField<T extends object>({
82 field: f.k,
83 headerName: f.headerName ?? (typeof f.label === 'string' ? f.label : labelFromKey(f.k)),
84 disableColumnMenu: true,
85 - valueGetter({ value }: any) {
86 - return (f.toField || _.identity)(value)
87 - },
85 + valueGetter: (v: any) => (f.toField || _.identity)(v),
86 ...f.$width ? { [f.$width >= 8 ? 'width' : 'flex']: f.$width } : (!def?.width && !def?.flex && { flex: 1 }),
87 renderCell: f.$render,
88 mergeRender: f.$mergeRender,
@@ -211,4 +209,4 @@ const byType: Dict<{ field?: Partial<FieldDescriptor>, column?: Partial<GridColD
209 renderCell: ({ value }) => value && new Date(value).toLocaleString(),
210 }
211 }
214 -}
\ No newline at end of file
212 +}
admin/src/DataTable.ts
+11 -13
@@ -1,5 +1,6 @@
1 -import { DataGrid, DataGridProps, enUS, getGridStringOperators, GridColDef, GridFooter, GridFooterContainer,
1 +import { DataGrid, DataGridProps, getGridStringOperators, GridColDef, GridFooter, GridFooterContainer,
2 GridValidRowModel, useGridApiRef, GridRenderCellParams } from '@mui/x-data-grid'
3 +import { enUS } from '@mui/x-data-grid/locales'
4 import { Alert, Box, BoxProps, Breakpoint, LinearProgress, useTheme } from '@mui/material'
5 import { createElement as h, Fragment, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react'
6 import { callable, Callback, Falsy, newDialog, onlyTruthy, useGetSize } from '@hfs/shared'
@@ -52,10 +53,6 @@ export function DataTable({ columns, initialState={}, actions, actionsProps, ini
53 const res = op.getApplyFilterFn(item, col)
54 return res && _.negate(res)
55 },
55 - ...op.getApplyFilterFnV7 && { getApplyFilterFnV7(item, col) {
56 - const res = op.getApplyFilterFnV7?.(item, col)
57 - return res ? _.negate(res) : null
58 - } },
56 label: "(not) " + (localeText['filterOperator' + _.upperFirst(op.value)] || op.value)
57 } satisfies typeof op
58 ])
@@ -66,13 +63,14 @@ export function DataTable({ columns, initialState={}, actions, actionsProps, ini
63 originalRenderCell: col.renderCell || true,
64 renderCell(params: GridRenderCellParams) {
65 const { columns } = params.api.store.getSnapshot()
69 - return h(Box, { maxHeight: '100%', ...col.cellInnerProps, sx: { textWrap: 'wrap', ...callable(sx as any, params) } }, // wrap if necessary, but stay within the row
66 + return h(Box, { maxHeight: '100%', ...col.cellInnerProps, sx: { textWrap: 'wrap', lineHeight: '1.2em', ...callable(sx as any, params) } }, // wrap if necessary, but stay within the row
67 col.renderCell ? col.renderCell(params) : params.formattedValue,
68 col.mergeRender && h(Flex, { fontSize: 'smaller', flexWrap: 'wrap', mt: '1px', rowGap: 0, ...col.mergeRenderSx }, // wrap, normally causing overflow/hiding, if it doesn't fit
69 ...onlyTruthy(_.map(col.mergeRender, (props, other) => {
70 if (!props || columns.columnVisibilityModel[other] !== false) return null
71 const rendered = renderCell({ ...columns.lookup[other], ...props.override }, params.row)
75 - return rendered && h(Box, { ...props, ...{ override: undefined }, ...compact && { lineHeight: '1em' } }, rendered)
72 + // keep mergeRender permissive for editor autocomplete, then narrow only at the render boundary
73 + return rendered && h(Box as any, { ...props, ...{ override: undefined }, ...compact && { lineHeight: '1em' } }, rendered)
74 }))
75 )
76 )
@@ -152,10 +150,9 @@ export function DataTable({ columns, initialState={}, actions, actionsProps, ini
150 },
151 slots: {
152 noRowsOverlay: () => initializing ? null : h(Center, {}, noRows || "No entries"),
155 - footer: CustomFooter,
153 + footer: () => h(CustomFooter, { add: wrappedFooterSide }),
154 },
155 slotProps: {
158 - footer: { add: wrappedFooterSide } as any, // 'add' is introduced by CustomFooter
156 pagination: {
157 labelRowsPerPage: "Rows",
158 ...!causingScrolling && {
@@ -217,11 +214,12 @@ export function DataTable({ columns, initialState={}, actions, actionsProps, ini
214 function renderCell(col: GridColDef, row: any) {
215 const api = apiRef.current
216 let value = row[col.field]
220 - if (col.valueGetter)
221 - value = col.valueGetter({ value, api, row, field: col.field, id: row.id } as any)
217 + if (col.valueGetter) // @ts-ignore
218 + value = col.valueGetter(value, row, col, api)
219 const render = (col as any).originalRenderCell || col.renderCell
220 return render && render !== true ? render({ value, row, api, ...row })
224 - : col.valueFormatter ? col.valueFormatter({ value, ...row })
221 + // @ts-ignore
222 + : col.valueFormatter ? col.valueFormatter(value, row, col, api)
223 : value
224 }
225 }
@@ -231,4 +229,4 @@ function CustomFooter({ add, ...props }: { add: ReactNode }) {
229 }
230
231 // required in case of fillFlex:true
234 -export const fillFlexParentSx = { display: 'flex', flexDirection: 'column' } as const
\ No newline at end of file
232 +export const fillFlexParentSx = { display: 'flex', flexDirection: 'column' } as const
admin/src/DateTimeField.ts
+6 -4
@@ -2,7 +2,7 @@ import { DateTimePicker } from '@mui/x-date-pickers'
2 import dayjs from 'dayjs'
3 import { FieldProps } from '@hfs/mui-grid-form'
4 import { createElement as h } from 'react'
5 -import { Box, FormHelperText } from '@mui/material'
5 +import { Box } from '@mui/material'
6 import { isTimestampString, objSameKeys } from './misc'
7
8 export function DateTimeField({ onChange, error, helperText, ...rest }: FieldProps<Date>) {
@@ -13,10 +13,12 @@ export function DateTimeField({ onChange, error, helperText, ...rest }: FieldPro
13 onChange(v: any) {
14 onChange(v && new Date(v), { was: rest.value, event: undefined })
15 },
16 - slotProps: { // under 400, not all buttons fit, so we sacrifice 'cancel' as you can still tap outside the dialog
17 - actionBar: { actions: ['clear', ...window.innerWidth < 400 ? [] : ['cancel'] as const, 'today', 'accept'] }
16 + slotProps: {
17 + // keep the same field look as StringField (filled variant) for visual consistency
18 + textField: { variant: 'filled', error, helperText },
19 + // under 400, not all buttons fit, so we sacrifice 'cancel' as you can still tap outside the dialog
20 + actionBar: { actions: ['clear', ...(window.innerWidth < 400 ? [] : ['cancel'] as const), 'today', 'accept'] }
21 }
22 }),
20 - helperText && h(FormHelperText, { error }, helperText),
23 )
24 }
admin/src/FileField.ts
+1
@@ -14,6 +14,7 @@ export default function FileField({ value, onChange, files=true, folders=false,
14 ...props,
15 value,
16 onChange,
17 + size: 'small',
18 wrap: true,
19 end: h(IconBtn, {
20 icon: Eject,
admin/src/FileForm.ts
+4 -4
@@ -23,7 +23,7 @@ import {
23 Check, ContentCopy, ContentCut, ContentPaste, Delete, Edit, QrCode2, Save, RestartAlt
24 } from '@mui/icons-material'
25 import { moveVfs } from './VfsTree'
26 -import QrCreator from 'qr-creator';
26 +import QrCreator from 'qr-creator'
27 import { AddVfsBtn } from './VfsMenuBar'
28 import { SYS_ICONS } from '@hfs/frontend/src/sysIcons'
29 import { hIcon } from '@hfs/frontend/src/misc'
@@ -69,7 +69,7 @@ export default function FileForm({ file, addToBar, statusApi, accounts, saved, i
69 const barColors = useDialogBarColors()
70 const { movingFile } = useSnapState()
71
72 - const needSourceWarning = !hasSource && h(Box, { color: 'warning.main', component: 'span' }, "Works only on folders with disk source! ")
72 + const needSourceWarning = !hasSource && h(Box as any, { color: 'warning.main', component: 'span' }, "Works only on folders with disk source! ")
73 const show: Record<keyof VfsPerms, boolean> = {
74 can_read: !isLink,
75 can_see: true,
@@ -409,9 +409,9 @@ function LinkField({ value, statusApi }: LinkFieldProps) {
409 fill: color, // foreground color
410 background: null, // color or null for transparent
411 size: 300 // in pixels
412 - }, canvas);
412 + }, canvas)
413 } catch (error) {
414 - console.error('Error generating QR code:', error);
414 + console.error('Error generating QR code:', error)
415 }
416 }
417 }
admin/src/FilePicker.ts
+2 -2
@@ -108,7 +108,7 @@ export default function FilePicker({ onSelect, multiple=true, files=true, folder
108 },
109 sx: { flex: 1, display: 'flex', flexDirection: 'column' }
110 },
111 - !list.length ? h(Center, { flex: 1, mt: '4em' }, connecting ? spinner() : "No elements in this folder")
111 + !list.length ? h(Center as any, { sx: { flex: 1 }, mt: '4em' }, connecting ? spinner() : "No elements in this folder")
112 : h(FixedSizeList, {
113 width: '100%', height: listHeight,
114 itemSize: 46, itemCount: filteredList.length, overscanCount: 5,
@@ -194,4 +194,4 @@ export function ListLsItem({ it }: { it: LsEntry }) {
194 ml: 4, mr: 1,
195 }, formatBytes(it.s))
196 )
197 -}
\ No newline at end of file
197 +}
admin/src/InstalledPlugins.ts
+3 -3
@@ -18,14 +18,14 @@ import { showPluginOptions, evalWrapper } from './pluginOptions'
18
19 // updates=true will show the "check updates" version of the page
20 export default function InstalledPlugins({ updates }: { updates?: true }) {
21 - const { list, error, setList, initializing } = useApiList(updates ? 'get_plugin_updates' : 'get_plugins', {}, {
21 + const { list, error, setList, initializing } = useApiList<any>(updates ? 'get_plugin_updates' : 'get_plugins', {}, {
22 map(x: any) { x.config &&= tryJson(x.config, s => evalWrapper('()=>('+s+')')()) }
23 })
24 const [sortAgain, setSortAgain] = useState(0)
25 useEffect(() => {
26 setList(list =>
27 _.sortBy(list, x => (x.error ? 0 : x.started ? 1 : x.badApi ? 2 : 3) + treatPluginName(x.repo?.split('/').reverse().join('/') || x.id).toLowerCase()))
28 - }, [list.length, sortAgain]);
28 + }, [list.length, sortAgain])
29 const size = 'small'
30 const { pause, pauseButton } = usePauseButton("plugins", () => getSingleConfig(CFG.suspend_plugins).then(x => !x), {
31 async onClick() {
@@ -52,7 +52,7 @@ export default function InstalledPlugins({ updates }: { updates?: true }) {
52 flex: .3,
53 minWidth: 150,
54 renderCell: renderName,
55 - valueGetter({ row }) { return row.repo || row.id },
55 + valueGetter(_value: any, row: any) { return row.repo || row.id },
56 mergeRender: { [updates ? 'changelog' : 'description']: { fontSize: 'x-small' } }
57 },
58 {
admin/src/LangPage.ts
+1 -1
@@ -35,7 +35,7 @@ export default function LangPage({ setTitleSide }: PageProps) {
35 {
36 field: 'code',
37 width: 110,
38 - valueFormatter: ({ value }) => value?.toUpperCase(),
38 + valueFormatter: (value: string | undefined) => value?.toUpperCase(),
39 },
40 {
41 field: 'version',
admin/src/LogsPage.ts
+11 -11
@@ -13,7 +13,7 @@ import {
13 import {
14 NetmaskField, Flex, IconBtn, useBreakpoint, usePauseButton, useToggleButton, Country,
15 hTooltip, Btn, wikiLink
16 -} from './mui';
16 +} from './mui'
17 import _ from 'lodash'
18 import {
19 AutoDelete, LinkOff, ClearAll, Delete, Download, Settings, SmartToy, Terminal, ContentCopy
@@ -21,7 +21,7 @@ import {
21 import { ConfigForm } from './ConfigForm'
22 import { BoolField, SelectField } from '@hfs/mui-grid-form'
23 import { toast, useDialogBarColors } from './dialog'
24 -import { BlockIpBtn } from './blockIp';
24 +import { BlockIpBtn } from './blockIp'
25 import { ALL as COUNTRIES } from './countries'
26
27 const logLabels = {
@@ -160,7 +160,7 @@ export function LogFile({ file, footerSide, hidden, limit, filter, ...rest }: Lo
160 headerName: "Timestamp",
161 type: 'dateTime',
162 width: 96,
163 - valueGetter: ({ value }) => new Date(value as string),
163 + valueGetter: (value) => new Date(value as string),
164 renderCell: ({ value }) => h(Fragment, {}, value.toLocaleDateString(), h('br'), value.toLocaleTimeString())
165 }
166 const ipColumn: DataTableColumn = {
@@ -236,7 +236,7 @@ export function LogFile({ file, footerSide, hidden, limit, filter, ...rest }: Lo
236 field: 'msg',
237 headerName: "Message",
238 flex: 1,
239 - mergeRender: { k: { override: { valueFormatter: ({ value }) => value !== 'log' && value } } }
239 + mergeRender: { k: { override: { valueFormatter: (value) => value !== 'log' && value } } }
240 }
241 ] : isIps || file === 'disconnections' ? [
242 tsColumn,
@@ -246,7 +246,7 @@ export function LogFile({ file, footerSide, hidden, limit, filter, ...rest }: Lo
246 field: 'country',
247 flex: 1,
248 hideUnder: !showCountry || 'md',
249 - valueGetter: ({ value }) => _.find(COUNTRIES, { code: value })?.name || value,
249 + valueGetter: (value) => _.find(COUNTRIES, { code: value })?.name || value,
250 renderCell: ({ row }) => h(Country, { code: row.country, long: true, def: '-' }),
251 },
252 !isIps && {
@@ -259,7 +259,7 @@ export function LogFile({ file, footerSide, hidden, limit, filter, ...rest }: Lo
259 {
260 headerName: "Country",
261 field: 'country',
262 - valueGetter: ({ row }) => row.extra?.country,
262 + valueGetter: (_value: any, row: any) => row.extra?.country,
263 hideUnder: !showCountry || 'xl',
264 renderCell: ({ value }) => h(Country, { code: value, def: '-' }),
265 },
@@ -284,21 +284,21 @@ export function LogFile({ file, footerSide, hidden, limit, filter, ...rest }: Lo
284 width: 70,
285 hideUnder: 'xl',
286 renderCell: ({ value }) => hTooltip(prefix(value + ' - ', httpCodes[value]) || "Unknown", undefined,
287 - h(Box, { bgcolor: '#888a', color: '#fff', borderRadius: '.3em', p: '.05em .2em' }, value))
287 + h(Box, { bgcolor: '#888a', color: '#fff', borderRadius: '.3em', p: '.05em .3em', lineHeight: '1.2em' }, value))
288 },
289 {
290 field: 'length',
291 headerName: "Size",
292 type: 'number',
293 hideUnder: 'md',
294 - valueFormatter: ({ value }) => formatBytes(value as number)
294 + valueFormatter: (value) => formatBytes(value as number)
295 },
296 {
297 headerName: "Agent",
298 field: 'ua',
299 width: 60,
300 hideUnder: !showAgent || 'md',
301 - valueGetter: ({ row }) => row.extra?.ua,
301 + valueGetter: (_value: any, row: any) => row.extra?.ua,
302 renderCell: ({ value }) => agentIcons(value),
303 },
304 {
@@ -322,7 +322,7 @@ export function LogFile({ file, footerSide, hidden, limit, filter, ...rest }: Lo
322 if (_.isArray(ul))
323 return path + ul.join(' + ')
324 if (!path.startsWith(API_URL))
325 - return [path, query && h(Box, { key: 0, component: 'span', color: 'text.secondary', fontSize: 'smaller' }, '?', query)]
325 + return [path, query && h(Box as any, { key: 0, component: 'span', color: 'text.secondary', fontSize: 'smaller' }, '?', query)]
326 const name = path.slice(API_URL.length)
327 const params = query && ': ' + Array.from(new URLSearchParams(query)).map(x => `${x[0]}=${tryJson(x[1]) ?? x[1]}`).join(' ; ')
328 return "API " + name + params
@@ -330,7 +330,7 @@ export function LogFile({ file, footerSide, hidden, limit, filter, ...rest }: Lo
330 },
331 {
332 field: 'agentText',
333 - valueGetter: ({ row }) => row.extra?.ua,
333 + valueGetter: (_value: any, row: any) => row.extra?.ua,
334 headerName: "Agent text",
335 flex: 2,
336 hideUnder: true,
admin/src/MonitorPage.ts
+9 -7
@@ -189,7 +189,7 @@ function Connections() {
189 type: 'dateTime',
190 width: 96,
191 hideUnder: 'lg',
192 - valueFormatter: ({ value }) => new Date(value as string).toLocaleTimeString()
192 + valueFormatter: (value) => new Date(value as string).toLocaleTimeString()
193 },
194 {
195 field: 'path',
@@ -197,17 +197,19 @@ function Connections() {
197 flex: 1.5,
198 renderCell({ value, row }) {
199 if (!value || !row.op) return
200 + const rowContentSx = { display: 'flex', alignItems: 'center', height: '100%', minWidth: 0, gap: 1 } as const
201 if (row.op === 'browsing')
201 - return h(Box, {}, value, h(Box, { fontSize: 'x-small' }, "browsing"))
202 - return h(Fragment, {},
202 + return h(Box, { sx: rowContentSx }, h(Box, {}, value, h(Box, { fontSize: 'x-small' }, "browsing")))
203 + // keep icon and filename on the same row: datagrid v7 wraps cell content differently than before
204 + return h(Box, { sx: rowContentSx },
205 h(IconProgress, {
206 icon: row.archive ? FolderZip : row.op === 'upload' ? Upload : Download,
207 progress: row.opProgress ?? row.opOffset,
208 offset: row.opOffset,
209 title: md(formatPerc(row.opProgress) + (row.opTotal ? "\nTotal: " + formatBytes(row.opTotal) : '')),
208 - sx: { mr: 1 }
210 }),
210 - row.archive ? h(Box, {}, value, h(Box, {
211 + // clamp line-height locally so this cell doesn't inherit tall line metrics from datagrid wrappers
212 + h(Box, { lineHeight: '1.2em', minWidth: 0 }, row.archive ? h(Box, {}, value, h(Box, {
213 fontSize: 'x-small',
214 color: 'text.secondary'
215 }, row.archive))
@@ -216,7 +218,7 @@ function Connections() {
218 fontSize: 'x-small',
219 color: 'text.secondary'
220 }, value.slice(0, i))
219 - )),
221 + ))),
222 )
223 }
224 },
@@ -281,4 +283,4 @@ function Connections() {
283
284 function formatSpeedK(value: number | undefined) {
285 return value === undefined ? '' : formatSpeed(value * 1000, { digits: 1 })
284 -}
\ No newline at end of file
286 +}
admin/src/OnlinePlugins.ts
+2 -2
@@ -53,7 +53,7 @@ export default function OnlinePlugins() {
53 {
54 field: 'pushed_at',
55 headerName: "last update",
56 - valueGetter: ({ value }) => new Date(value).toLocaleDateString(),
56 + valueGetter: (value) => new Date(value).toLocaleDateString(),
57 },
58 {
59 field: 'license',
@@ -146,4 +146,4 @@ async function installPlugin(id: string, branch?: string): Promise<any> {
146 return installPlugin(id, branch)
147 throw e
148 }
149 -}
\ No newline at end of file
149 +}
admin/src/VfsPage.ts
+1 -1
@@ -128,7 +128,7 @@ export default function VfsPage({ setTitleSide }: PageProps) {
128 vfsNodeIcon(selectedFiles[0] as VfsNodeAdmin),
129 h(Flex, { flexWrap: 'wrap', gap: '0 0.5em' },
130 selectedFiles[0].name || "Home",
131 - h(Box, { component: 'span', color: 'text.secondary' }, ancestors.join(' /'))
131 + h(Box, { component: 'span', color: 'text.secondary' } as any, ancestors.join(' /'))
132 )
133 ),
134 dialogProps: { sx: { justifyContent: 'flex-end' } },
admin/src/VfsTree.ts
+37 -33
@@ -2,7 +2,7 @@
2
3 import { markVfsModified, prepareVfsUndo, state, useSnapState } from './state'
4 import { createElement as h, ReactElement, useCallback, useEffect, useRef, MouseEvent } from 'react'
5 -import { TreeItem, TreeView } from '@mui/x-tree-view'
5 +import { TreeItem, SimpleTreeView } from '@mui/x-tree-view'
6 import {
7 ChevronRight, ExpandMore, TheaterComedy, Folder, Home, Link, InsertDriveFileOutlined, Lock,
8 RemoveRedEye, Web, Upload, Cloud, Delete, HighlightOff, UnfoldMore, UnfoldLess
@@ -46,31 +46,30 @@ export default function VfsTree({ statusApi }:{ statusApi: ApiObject }) {
46 }
47 },
48 onDoubleClick: toggle,
49 - label:
50 - h(Box, {
51 - draggable: !isRoot,
52 - onDragStart() {
53 - dragging.current = id
54 - },
55 - onDragOver(ev) {
56 - if (!isFolder) return
57 - const src = dragging.current
58 - if (src?.startsWith(id) && !src.slice(id.length + 1, -1).includes('/')) return // dragging node (src) must not be direct child of destination (id)
59 - ev.preventDefault()
60 - },
61 - async onDrop() {
62 - const from = dragging.current
63 - if (!from) return
64 - const fromName = id2vfsNode.get(from)?.name // won't work after moving
49 + label: h(Box, {
50 + draggable: !isRoot,
51 + onDragStart() {
52 + dragging.current = id
53 + },
54 + onDragOver(ev) {
55 + if (!isFolder) return
56 + const src = dragging.current
57 + if (src?.startsWith(id) && !src.slice(id.length + 1, -1).includes('/')) return // dragging node (src) must not be direct child of destination (id)
58 + ev.preventDefault()
59 + },
60 + async onDrop() {
61 + const from = dragging.current
62 + if (!from) return
63 + const fromName = id2vfsNode.get(from)?.name // won't work after moving
64 if (moveVfs(from, id))
65 toast(`Moved "${fromName}" under "${id2vfsNode.get(id)?.name}"`, 'success')
67 - },
68 - sx: {
69 - display: 'flex',
70 - gap: '.5em',
71 - minHeight: '1.8em', pt: '.2em', // comfy, make single-line ones taller
72 - }
66 },
67 + sx: {
68 + display: 'flex',
69 + gap: '.5em',
70 + minHeight: '1.8em', pt: '.2em', // comfy, make single-line ones taller
71 + }
72 + },
73 h(Box, { display: 'flex', flex: 0, },
74 vfsNodeIcon(node),
75 // attributes, as icons
@@ -94,11 +93,9 @@ export default function VfsTree({ statusApi }:{ statusApi: ApiObject }) {
93 ),
94 isRoot ? "Home folder" : name
95 ),
97 - collapseIcon: h(ExpandMore, { onClick: toggle }),
98 - expandIcon: h(ChevronRight, { onClick: toggle }),
99 - nodeId: id
96 + itemId: id
97 }, with_(node.source && isFolder ? "files from " + node.source : !node.children?.length && isRoot && "nothing here", x =>
101 - x && h(TreeItem, { nodeId: SPECIAL_TREE_ITEM + id, label: h('i', {}, x) })),
98 + x && h(TreeItem, { itemId: SPECIAL_TREE_ITEM + id, label: h('i', {}, x) })),
99 ...node.children?.map(x => h(Branch, { key: x.id, node: x })) || []
100 )
101
@@ -141,10 +138,10 @@ export default function VfsTree({ statusApi }:{ statusApi: ApiObject }) {
138 h(Typography, { variant: 'h6' }, "Virtual File System"),
139 h(VfsMenuBar, { statusApi, add: toggleBtn }),
140 ),
144 - vfs && h(TreeView, {
141 + vfs && h(SimpleTreeView, {
142 ref,
146 - expanded: toMutable(expanded),
147 - selected: selectedFiles.map(x => x.id),
143 + expandedItems: toMutable(expanded),
144 + selectedItems: selectedFiles.map(x => x.id),
145 multiSelect: true,
146 id: treeId,
147 sx: {
@@ -153,10 +150,17 @@ export default function VfsTree({ statusApi }:{ statusApi: ApiObject }) {
150 maxWidth: ref.current && `calc(100vw - ${16 + ref.current.offsetLeft}px)`, // limit possible horizontal scrolling to this element
151 '& ul': { borderLeft: '1px dashed #444', marginLeft: '15px', paddingLeft: '15px' },
152 },
156 - onNodeSelect(_ev, ids) {
157 - state.selectedFiles = onlyTruthy(wantArray(ids).map(id => id2vfsNode.get(id)))
153 + slots: {
154 + collapseIcon: ExpandMore,
155 + expandIcon: ChevronRight,
156 + },
157 + onSelectedItemsChange(_ev, ids) {
158 + const selectedIds = wantArray(ids) as string[]
159 + state.selectedFiles = onlyTruthy(selectedIds.map(id => id2vfsNode.get(id)))
160 // this is the only point where we have special node ids that don't fit selectedFiles
159 - state.vfsShowDiskContentFor = ids.length === 1 && ids[0]?.[0] === SPECIAL_TREE_ITEM && id2vfsNode.get(ids[0].slice(1))?.source || ''
161 + state.vfsShowDiskContentFor = selectedIds.length === 1
162 + && selectedIds[0][0] === SPECIAL_TREE_ITEM
163 + && id2vfsNode.get(selectedIds[0].slice(1))?.source || ''
164 }
165 }, h(Branch, { node: vfs as Readonly<VfsNodeAdmin> }))
166 )
admin/src/index.scss
+7 -1
@@ -36,12 +36,18 @@ form { max-width: 100%; } // make fields with unbreakable text (LinkField) to no
36 .MuiSvgIcon-root {
37 vertical-align: bottom;
38 }
39 -div.MuiTreeItem-content { padding: 0; } // remove wasting horizontal padding
39 +div.MuiTreeItem-content {
40 + padding-top: 1px; // denser
41 + padding-bottom: 0;
42 +}
43 .MuiDataGrid-columnHeaders {
44 background-color: #8882;
45 }
46 +.MuiDataGrid-virtualScrollerRenderZone .MuiDataGrid-row // make it heavier
47 .MuiDataGrid-cell {
48 line-height: 1.2em;
49 + display: flex;
50 + align-items: center;
51 }
52 .MuiDataGrid-filterForm { flex-wrap: wrap; justify-content: space-evenly; row-gap: 1em; } // fit on mobile
53
admin/src/mui.ts
+13 -13
@@ -8,14 +8,13 @@ import {
8 ForwardedRef, useState, useMemo, isValidElement, ElementType
9 } from 'react'
10 import { Box, BoxProps, Breakpoint, ButtonProps, CircularProgress, IconButton, IconButtonProps, Link, LinkProps,
11 - Tooltip, TooltipProps, useMediaQuery } from '@mui/material'
11 + Tooltip, TooltipProps, useMediaQuery, Button } from '@mui/material'
12 import {
13 anyDialogOpen, closeDialog, formatPerc, isIpLan, isIpLocalHost, prefix, WIKI_URL, with_, Functionable, callable
14 } from './misc'
15 import { dontBotherWithKeys, restartAnimation, useBatch, useStateMounted } from '@hfs/shared'
16 import { Promisable, StringField } from '@hfs/mui-grid-form'
17 import { alertDialog, confirmDialog, toast } from './dialog'
18 -import { LoadingButton } from '@mui/lab'
18 import { Link as RouterLink, LinkProps as RouterLinkProps, useNavigate } from 'react-router-dom'
19 import { SvgIconProps } from '@mui/material/SvgIcon/SvgIcon'
20 import _ from 'lodash'
@@ -68,15 +67,15 @@ export function IconProgress({ icon, progress, offset, title, sx }: IconProgress
67 value: (offset || 1e-7) * 100,
68 variant: 'determinate',
69 size: 32,
71 - sx: { display: 'flex', ...sx }, // workaround: without this the element has 0 width when the space is crammy (monitor/file)
70 + sx: _.defaults(sx as any, { display: 'flex' }) as any, // workaround: without this the element has 0 width when the space is crammy (monitor/file)
71 }),
72 )
73 )
74 }
75
77 -type FlexProps = SxProps & { vert?: boolean, center?: boolean, children?: ReactNode, props?: BoxProps, component?: ElementType }
76 +type FlexProps = { vert?: boolean, center?: boolean, children?: ReactNode, props?: BoxProps, component?: ElementType } & Record<string, any>
77 export function Flex({ vert=false, center=false, children=null, props={}, component, ...rest }: FlexProps) {
79 - return h(Box, {
78 + return h(Box as any, {
79 sx: {
80 display: 'flex',
81 gap: '.8em',
@@ -84,7 +83,7 @@ export function Flex({ vert=false, center=false, children=null, props={}, compon
83 alignItems: vert ? undefined : 'center',
84 ...center && { justifyContent: 'center' },
85 ...rest,
87 - },
86 + } as any,
87 component,
88 ...props
89 }, children)
@@ -140,7 +139,7 @@ export interface BtnProps extends Omit<ButtonProps & IconButtonProps,'disabled'|
139 doneAnimation?: boolean
140 tooltipProps?: Partial<TooltipProps>
141 modified?: boolean
143 - loading?: boolean
142 + loading?: boolean | null
143 onClick?: (...args: Parameters<NonNullable<ButtonProps['onClick']>>) => Promisable<any>
144 }
145
@@ -176,7 +175,8 @@ export const Btn = forwardRef(({ icon, title, onClick, disabled, progress, link,
175 },
176 } as const, rest)
177 const iconElement = isValidElement(icon) ? icon : (icon && h(icon))
179 - let ret: ReactElement = children && showLabel ? h(LoadingButton, _.merge({
178 + let ret: ReactElement = children && showLabel ? h(Button as any, _.merge({
179 + // mui v6 moved LoadingButton behavior into Button, but current typings here still miss loading props
180 variant: 'contained',
181 startIcon: iconElement,
182 loading: Boolean(loading || loadingState || progress),
@@ -184,7 +184,7 @@ export const Btn = forwardRef(({ icon, title, onClick, disabled, progress, link,
184 loadingIndicator: typeof progress !== 'number' ? undefined
185 : h(CircularProgress, { size: '1rem', value: progress*100, variant: 'determinate' }),
186 children: showLabel && children,
187 - } as const, common, (!showLabel || !children) && { sx: { minWidth: 'auto', px: 1, py: '7px', '& span': { mx:0 }, } }))
187 + } as const, common, (!showLabel || !children) && { sx: { minWidth: 'auto', px: 1, py: '7px', '& span': { mx:0 }, } }) as any)
188 : h(IconButton, _.merge(common, {
189 sx: { height: 'fit-content' }, TouchRippleProps: { 'aria-hidden': true },
190 // we need a direct accessible name on the actual clickable element for testing
@@ -314,7 +314,7 @@ export function Country({ code, ip, def, long, short }: { code: string, ip?: str
314 const country = code && _.find(COUNTRIES, { code })
315 return !country ? h(Fragment, {}, def)
316 : hTooltip(long ? undefined : country.name, undefined, h('span', {},
317 - h(Box, {
317 + h(Box as any, {
318 className: `fflag fflag-${code.toUpperCase()}`,
319 component: 'span',
320 mr: 1,
@@ -331,8 +331,8 @@ async function ip2countryBatch(ips: string[]) {
331 // force you to think of aria when adding a tooltip
332 export function hTooltip(title: ReactNode, ariaLabel: string | undefined, children: ReactElement, props?: Omit<TooltipProps, 'title' | 'children'> & { key?: any }) {
333 return h(Tooltip, { title, children,
334 - ...ariaLabel === '' ? { 'aria-hidden': true } : { 'aria-label': ariaLabel || _.isString(title) && title || undefined },
335 - componentsProps: { popper: { sx: { whiteSpace: 'pre-wrap', ...props?.sx } } },
334 + ...(ariaLabel === '' ? { 'aria-hidden': true } : { 'aria-label': ariaLabel || _.isString(title) && title || undefined }),
335 + componentsProps: { popper: { sx: { whiteSpace: 'pre-wrap', ...props?.sx } } } as any,
336 ...props
337 })
338 -}
\ No newline at end of file
338 +}
e2e/serial.spec.ts
+31 -29
@@ -12,53 +12,55 @@ export const fileToUpload = {
12
13 test('upload1', async ({ page, context, browserName }) => {
14 if (browserName !== 'chromium') return // only chromium has cdpSession
15 - await page.goto(FRONTEND_URL);
16 - await page.getByRole('button', { name: 'Login' }).click();
17 - await page.getByRole('textbox', { name: 'Username' }).fill(username);
18 - await page.getByRole('textbox', { name: 'Password' }).fill(password);
19 - await page.getByRole('button', { name: 'Continue' }).click();
20 - await page.locator('div').filter({ hasText: 'Logged in' }).nth(3).click();
15 + await page.goto(FRONTEND_URL)
16 + await page.getByRole('button', { name: 'Login' }).click()
17 + await page.getByRole('textbox', { name: 'Username' }).fill(username)
18 + await page.getByRole('textbox', { name: 'Password' }).fill(password)
19 + await page.getByRole('button', { name: 'Continue' }).click()
20 + await page.locator('div').filter({ hasText: 'Logged in' }).nth(3).click()
21
22 - await page.getByRole('link', { name: 'for-admins, Folder' }).click();
23 - await page.getByRole('link', { name: 'upload, Folder' }).click();
22 + await page.getByRole('link', { name: 'for-admins, Folder' }).click()
23 + await page.getByRole('link', { name: 'upload, Folder' }).click()
24
25 - await page.getByRole('button', { name: 'Options' }).click();
26 - const pageAdminPromise = page.waitForEvent('popup');
27 - await page.getByRole('button', { name: 'Admin-panel' }).click();
28 - const pageAdmin = await pageAdminPromise;
25 + await page.getByRole('button', { name: 'Options' }).click()
26 + const pageAdminPromise = page.waitForEvent('popup')
27 + await page.getByRole('button', { name: 'Admin-panel' }).click()
28 + const pageAdmin = await pageAdminPromise
29 await pageAdmin.goto(ADMIN_URL + '#/monitoring'); // cross-device way of changing page
30 - await page.locator('div').filter({ hasText: 'xOptionsAdmin-panelSort by:' }).nth(2).click();
31 - await page.getByRole('button', { name: 'Close' }).click();
32 - await page.getByRole('button', { name: 'Upload' }).click();
33 - const fileChooserPromise = page.waitForEvent('filechooser');
34 - await page.getByRole('button', { name: 'Pick files' }).click();
35 - const fileChooser = await fileChooserPromise;
36 - await fileChooser.setFiles(fileToUpload);
30 + await page.locator('div').filter({ hasText: 'xOptionsAdmin-panelSort by:' }).nth(2).click()
31 + await page.getByRole('button', { name: 'Close' }).click()
32 + await page.getByRole('button', { name: 'Upload' }).click()
33 + const fileChooserPromise = page.waitForEvent('filechooser')
34 + await page.getByRole('button', { name: 'Pick files' }).click()
35 + const fileChooser = await fileChooserPromise
36 + await fileChooser.setFiles(fileToUpload)
37 // can't do without cdp to slow down the upload. I tried using route.continue, but i can't send half-body keeping the full content-length, and i also cannot pass a stream (to throttle)
38 const cdpSession = await context.newCDPSession(page)
39 await cdpSession.send('Network.emulateNetworkConditions', NETWORK_PRESETS.Regular2G)
40 - await page.getByRole('button', { name: 'Edit' }).click();
40 + await page.getByRole('button', { name: 'Edit' }).click()
41 const renameDialog = page.locator('.dialog-prompt')
42 const renameInput = renameDialog.getByRole('textbox')
43 await expect(renameInput).toHaveValue(fileToUpload.name) // promptDialog initializes the field value in useEffect, so we wait for that init to avoid our fill being overwritten
44 - await renameInput.fill(uploadName);
45 - await renameDialog.getByRole('button', { name: 'Continue' }).click();
44 + await renameInput.fill(uploadName)
45 + await renameDialog.getByRole('button', { name: 'Continue' }).click()
46 await expect(page.getByText(uploadName)).toBeVisible() // rename was effective
47 // we send the upload, slowly, so that we can interrupt it in the admin-panel to test the upload resume
48 - await page.getByRole('button', { name: 'Send 1 file' }).click();
49 - const uploadCells = pageAdmin.getByRole('cell', { name: `${uploadName} /for-admins/upload` })
48 + await page.getByRole('button', { name: 'Send 1 file' }).click()
49 + const uploadCells = pageAdmin.locator('.MuiDataGrid-cell')
50 + .filter({ hasText: uploadName })
51 + .filter({ hasText: '/for-admins/upload' })
52 await expect(uploadCells.first()).toBeVisible()
53 // during upload resume, monitoring can briefly show two rows for the same path
54 await uploadCells.last().click()
55 await clickIconBtn('Disconnect', pageAdmin)
56 await clickIconBtn('Close', pageAdmin)
57 await pageAdmin.close()
56 - await page.getByText('Copy links').click();
57 - await page.getByText('Operation successful').click();
58 - await page.getByRole('button', { name: 'Close' }).click();
58 + await page.getByText('Copy links').click()
59 + await page.getByText('Operation successful').click()
60 + await page.getByRole('button', { name: 'Close' }).click()
61 await cdpSession?.send('Network.emulateNetworkConditions', NETWORK_PRESETS.NoThrottle)
62 clearUploads()
61 -});
63 +})
64
65 const NETWORK_PRESETS = {
66 Offline: {
@@ -81,7 +83,7 @@ const NETWORK_PRESETS = {
83 latency: 300,
84 connectionType: 'cellular2g',
85 },
84 -} as const;
86 +} as const
87
88 // some interactions, no screenshots
89 test('admin2', async ({ page }) => {
mui-grid-form/index.ts
+32 -11
@@ -6,11 +6,9 @@ import {
6 } from 'react'
7 import { Box, BoxProps, Button, Tooltip } from '@mui/material'
8 import { Save } from '@mui/icons-material'
9 -import { LoadingButton } from '@mui/lab'
9 import _ from 'lodash'
10 import { StringField } from './StringField'
12 -import Grid from '@mui/material/Unstable_Grid2'
13 -import { GridProps } from '@mui/material/Grid/Grid'
11 +import Grid, { Grid2Props as GridProps } from '@mui/material/Grid2'
12 import { useDebounce } from 'usehooks-ts'
13 export * from './SelectField'
14 export * from './misc-fields'
@@ -145,12 +143,13 @@ export function Form<Values extends Dict>({
143 if (!row)
144 return null
145 if (isValidElement(row))
148 - return h(Grid, { key: idx, xs: 12 }, row)
146 + return h(Grid, { key: idx, size: 12 }, row)
147 if (defaults)
148 row = { ...defaults?.(row), ...row }
149 const { k, fromField=_.identity, toField=_.identity, getError, error,
150 xs=12, sm, md, lg, xl, comp=StringField, before, after, parentProps,
151 ...field } = row
152 + const size = legacySpanToGridSize({ xs, sm, md, lg, xl })
153 let errMsg = errors[k] || error || fieldExceptions[k]
154 if (errMsg === true)
155 errMsg = "Not valid"
@@ -183,8 +182,8 @@ export function Form<Values extends Dict>({
182 field.helperText = h(Fragment, {}, ...field.helperText)
183 if (errMsg) // special rendering when we have both error and helperText. "hr" would be nice but issues a warning because contained in a <p>
184 field.helperText = !field.helperText ? errMsg
186 - : h(Box, { color: 'text.primary', component: 'span' },
187 - h(Box, {
185 + : h(Box as any, { color: 'text.primary', component: 'span' },
186 + h(Box as any, {
187 color: 'error.main',
188 style: { borderBottom: '1px solid' },
189 component: 'span', display: 'block' // avoid console warning, but keep it on separate line
@@ -195,7 +194,7 @@ export function Form<Values extends Dict>({
194 field.label = labelFromKey(k)
195 }
196 const n = (keyMet[k] = (keyMet[k] || 0) + 1)
198 - return h(Grid, { key: k ? k + n : idx, xs, sm, md, lg, xl, className: anyError && ERROR_CLASS, ...parentProps },
197 + return h(Grid, { key: k ? k + n : idx, size, className: anyError && ERROR_CLASS, ...parentProps },
198 before,
199 isValidElement(comp) ? comp : h(comp, field),
200 after
@@ -211,7 +210,8 @@ export function Form<Values extends Dict>({
210 position: 'sticky', bottom: 0, p: 1, m: -1, boxShadow: '0px 0px 15px #000',
211 },
212 barSx)
214 - }, h(Tooltip, { title: "ctrl + enter", children: h(LoadingButton, {
213 + }, h(Tooltip, { title: "ctrl + enter", children: h(Button as any, {
214 + // mui v6 moved LoadingButton behavior into Button, but current typings here still miss loading props
215 variant: 'contained',
216 startIcon: h(Save),
217 children: "Save",
@@ -220,7 +220,7 @@ export function Form<Values extends Dict>({
220 onClick() {
221 pleaseSubmitAndValidate()
222 },
223 - }) }),
223 + } as any) }),
224 ...addToBar,
225 )
226 )
@@ -254,8 +254,8 @@ export function Form<Values extends Dict>({
254 const v = getValueFor(k)
255 let err: ReactNode
256 try {
257 - err = await apis[k]?.getError?.(v, { values, fields })
258 - || await f.getError?.(v, { values, fields })
257 + err = (await apis[k]?.getError?.(v, { values, fields }))
258 + || (await f.getError?.(v, { values, fields }))
259 || fieldExceptions[k]
260 || false
261 }
@@ -301,3 +301,24 @@ export function labelFromKey(k: string) {
301 return _.upperFirst(k.indexOf('_') > 0 ? k.replace(/_/g, ' ')
302 : k.replace(/([a-z])([A-Z])/g, (_all, a, b) => a + ' ' + b.toLowerCase()))
303 }
304 +
305 +function legacySpanToGridSize({ xs, sm, md, lg, xl }: { xs?: unknown, sm?: unknown, md?: unknown, lg?: unknown, xl?: unknown }) {
306 + // keep compatibility with existing form descriptors still using xs/sm/md while grid2 expects size
307 + const sizeByBreakpoint = {
308 + xs: normalizeLegacySpan(xs),
309 + sm: normalizeLegacySpan(sm),
310 + md: normalizeLegacySpan(md),
311 + lg: normalizeLegacySpan(lg),
312 + xl: normalizeLegacySpan(xl),
313 + }
314 + if (sm === undefined && md === undefined && lg === undefined && xl === undefined)
315 + return sizeByBreakpoint.xs
316 + return sizeByBreakpoint as any
317 +}
318 +
319 +function normalizeLegacySpan(span: unknown) {
320 + // in legacy Grid, `true` means auto-grow width; in grid2 this is expressed with `size="grow"`
321 + if (span === true)
322 + return 'grow'
323 + return span
324 +}
package-lock.json
+614 -374
@@ -80,12 +80,12 @@
80 "@gregoranders/csv": "^0.0.13",
81 "@hfs/mui-grid-form": "*",
82 "@hfs/shared": "*",
83 - "@mui/icons-material": "^5.18.0",
84 - "@mui/lab": "^5.0.0-alpha.177",
85 - "@mui/material": "^5.18.0",
86 - "@mui/x-data-grid": "^6.20.4",
87 - "@mui/x-date-pickers": "^6.20.2",
88 - "@mui/x-tree-view": "^6.17.0",
83 + "@mui/icons-material": "^6.4.11",
84 + "@mui/lab": "^6.0.1-beta.34",
85 + "@mui/material": "^6.4.11",
86 + "@mui/x-data-grid": "^7.29.0",
87 + "@mui/x-date-pickers": "^7.29.0",
88 + "@mui/x-tree-view": "^7.29.0",
89 "dayjs": "^1.11.10",
90 "immer": "*",
91 "prismjs": "^1.29.0",
@@ -106,35 +106,122 @@
106 "vite": "^6.4.1"
107 }
108 },
109 - "admin/node_modules/@mui/x-data-grid": {
110 - "version": "6.20.4",
111 - "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-6.20.4.tgz",
112 - "integrity": "sha512-I0JhinVV4e25hD2dB+R6biPBtpGeFrXf8RwlMPQbr9gUggPmPmNtWKo8Kk2PtBBMlGtdMAgHWe7PqhmucUxU1w==",
109 + "admin/node_modules/@mui/icons-material": {
110 + "version": "6.5.0",
111 + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-6.5.0.tgz",
112 + "integrity": "sha512-VPuPqXqbBPlcVSA0BmnoE4knW4/xG6Thazo8vCLWkOKusko6DtwFV6B665MMWJ9j0KFohTIf3yx2zYtYacvG1g==",
113 + "license": "MIT",
114 "dependencies": {
114 - "@babel/runtime": "^7.23.2",
115 - "@mui/utils": "^5.14.16",
116 - "clsx": "^2.0.0",
117 - "prop-types": "^15.8.1",
118 - "reselect": "^4.1.8"
115 + "@babel/runtime": "^7.26.0"
116 + },
117 + "engines": {
118 + "node": ">=14.0.0"
119 + },
120 + "funding": {
121 + "type": "opencollective",
122 + "url": "https://opencollective.com/mui-org"
123 + },
124 + "peerDependencies": {
125 + "@mui/material": "^6.5.0",
126 + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
127 + "react": "^17.0.0 || ^18.0.0 || ^19.0.0"
128 + },
129 + "peerDependenciesMeta": {
130 + "@types/react": {
131 + "optional": true
132 + }
133 + }
134 + },
135 + "admin/node_modules/@mui/lab": {
136 + "version": "6.0.1-beta.36",
137 + "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-6.0.1-beta.36.tgz",
138 + "integrity": "sha512-af9lDmA9SZGEWF1XXk0EVBpfCITk9IKsvh9lLOZGdYaaHfQeCsqxGEDMvNO66j0P8EYoxpyry84LFCJYuLVtVw==",
139 + "license": "MIT",
140 + "dependencies": {
141 + "@babel/runtime": "^7.26.0",
142 + "@mui/base": "5.0.0-beta.70",
143 + "@mui/system": "^6.5.0",
144 + "@mui/types": "~7.2.24",
145 + "@mui/utils": "^6.4.9",
146 + "clsx": "^2.1.1",
147 + "prop-types": "^15.8.1"
148 + },
149 + "engines": {
150 + "node": ">=14.0.0"
151 + },
152 + "funding": {
153 + "type": "opencollective",
154 + "url": "https://opencollective.com/mui-org"
155 + },
156 + "peerDependencies": {
157 + "@emotion/react": "^11.5.0",
158 + "@emotion/styled": "^11.3.0",
159 + "@mui/material": "^6.5.0",
160 + "@mui/material-pigment-css": "^6.5.0",
161 + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
162 + "react": "^17.0.0 || ^18.0.0 || ^19.0.0",
163 + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
164 + },
165 + "peerDependenciesMeta": {
166 + "@emotion/react": {
167 + "optional": true
168 + },
169 + "@emotion/styled": {
170 + "optional": true
171 + },
172 + "@mui/material-pigment-css": {
173 + "optional": true
174 + },
175 + "@types/react": {
176 + "optional": true
177 + }
178 + }
179 + },
180 + "admin/node_modules/@mui/lab/node_modules/@mui/base": {
181 + "version": "5.0.0-beta.70",
182 + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.70.tgz",
183 + "integrity": "sha512-Tb/BIhJzb0pa5zv/wu7OdokY9ZKEDqcu1BDFnohyvGCoHuSXbEr90rPq1qeNW3XvTBIbNWHEF7gqge+xpUo6tQ==",
184 + "deprecated": "This package has been replaced by @base-ui/react",
185 + "license": "MIT",
186 + "dependencies": {
187 + "@babel/runtime": "^7.26.0",
188 + "@floating-ui/react-dom": "^2.1.1",
189 + "@mui/types": "~7.2.24",
190 + "@mui/utils": "^6.4.8",
191 + "@popperjs/core": "^2.11.8",
192 + "clsx": "^2.1.1",
193 + "prop-types": "^15.8.1"
194 },
195 "engines": {
196 "node": ">=14.0.0"
197 },
198 "funding": {
199 "type": "opencollective",
125 - "url": "https://opencollective.com/mui"
200 + "url": "https://opencollective.com/mui-org"
201 },
202 "peerDependencies": {
128 - "@mui/material": "^5.4.1",
129 - "@mui/system": "^5.4.1",
130 - "react": "^17.0.0 || ^18.0.0",
131 - "react-dom": "^17.0.0 || ^18.0.0"
203 + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
204 + "react": "^17.0.0 || ^18.0.0 || ^19.0.0",
205 + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
206 + },
207 + "peerDependenciesMeta": {
208 + "@types/react": {
209 + "optional": true
210 + }
211 }
212 },
134 - "admin/node_modules/reselect": {
135 - "version": "4.1.8",
136 - "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz",
137 - "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ=="
213 + "admin/node_modules/@mui/lab/node_modules/@mui/base/node_modules/@floating-ui/react-dom": {
214 + "version": "2.1.8",
215 + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz",
216 + "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==",
217 + "license": "MIT",
218 + "dependencies": {
219 + "@floating-ui/dom": "^1.7.6"
220 + },
221 + "peerDependencies": {
222 + "react": ">=16.8.0",
223 + "react-dom": ">=16.8.0"
224 + }
225 },
226 "frontend": {
227 "name": "@hfs/frontend",
@@ -200,6 +287,123 @@
287 "react-dom": "*"
288 }
289 },
290 + "mui-grid-form/node_modules/@mui/icons-material": {
291 + "version": "6.5.0",
292 + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-6.5.0.tgz",
293 + "integrity": "sha512-VPuPqXqbBPlcVSA0BmnoE4knW4/xG6Thazo8vCLWkOKusko6DtwFV6B665MMWJ9j0KFohTIf3yx2zYtYacvG1g==",
294 + "license": "MIT",
295 + "dependencies": {
296 + "@babel/runtime": "^7.26.0"
297 + },
298 + "engines": {
299 + "node": ">=14.0.0"
300 + },
301 + "funding": {
302 + "type": "opencollective",
303 + "url": "https://opencollective.com/mui-org"
304 + },
305 + "peerDependencies": {
306 + "@mui/material": "^6.5.0",
307 + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
308 + "react": "^17.0.0 || ^18.0.0 || ^19.0.0"
309 + },
310 + "peerDependenciesMeta": {
311 + "@types/react": {
312 + "optional": true
313 + }
314 + }
315 + },
316 + "mui-grid-form/node_modules/@mui/lab": {
317 + "version": "6.0.1-beta.36",
318 + "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-6.0.1-beta.36.tgz",
319 + "integrity": "sha512-af9lDmA9SZGEWF1XXk0EVBpfCITk9IKsvh9lLOZGdYaaHfQeCsqxGEDMvNO66j0P8EYoxpyry84LFCJYuLVtVw==",
320 + "license": "MIT",
321 + "dependencies": {
322 + "@babel/runtime": "^7.26.0",
323 + "@mui/base": "5.0.0-beta.70",
324 + "@mui/system": "^6.5.0",
325 + "@mui/types": "~7.2.24",
326 + "@mui/utils": "^6.4.9",
327 + "clsx": "^2.1.1",
328 + "prop-types": "^15.8.1"
329 + },
330 + "engines": {
331 + "node": ">=14.0.0"
332 + },
333 + "funding": {
334 + "type": "opencollective",
335 + "url": "https://opencollective.com/mui-org"
336 + },
337 + "peerDependencies": {
338 + "@emotion/react": "^11.5.0",
339 + "@emotion/styled": "^11.3.0",
340 + "@mui/material": "^6.5.0",
341 + "@mui/material-pigment-css": "^6.5.0",
342 + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
343 + "react": "^17.0.0 || ^18.0.0 || ^19.0.0",
344 + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
345 + },
346 + "peerDependenciesMeta": {
347 + "@emotion/react": {
348 + "optional": true
349 + },
350 + "@emotion/styled": {
351 + "optional": true
352 + },
353 + "@mui/material-pigment-css": {
354 + "optional": true
355 + },
356 + "@types/react": {
357 + "optional": true
358 + }
359 + }
360 + },
361 + "mui-grid-form/node_modules/@mui/lab/node_modules/@mui/base": {
362 + "version": "5.0.0-beta.70",
363 + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.70.tgz",
364 + "integrity": "sha512-Tb/BIhJzb0pa5zv/wu7OdokY9ZKEDqcu1BDFnohyvGCoHuSXbEr90rPq1qeNW3XvTBIbNWHEF7gqge+xpUo6tQ==",
365 + "deprecated": "This package has been replaced by @base-ui/react",
366 + "license": "MIT",
367 + "dependencies": {
368 + "@babel/runtime": "^7.26.0",
369 + "@floating-ui/react-dom": "^2.1.1",
370 + "@mui/types": "~7.2.24",
371 + "@mui/utils": "^6.4.8",
372 + "@popperjs/core": "^2.11.8",
373 + "clsx": "^2.1.1",
374 + "prop-types": "^15.8.1"
375 + },
376 + "engines": {
377 + "node": ">=14.0.0"
378 + },
379 + "funding": {
380 + "type": "opencollective",
381 + "url": "https://opencollective.com/mui-org"
382 + },
383 + "peerDependencies": {
384 + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
385 + "react": "^17.0.0 || ^18.0.0 || ^19.0.0",
386 + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
387 + },
388 + "peerDependenciesMeta": {
389 + "@types/react": {
390 + "optional": true
391 + }
392 + }
393 + },
394 + "mui-grid-form/node_modules/@mui/lab/node_modules/@mui/base/node_modules/@floating-ui/react-dom": {
395 + "version": "2.1.8",
396 + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz",
397 + "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==",
398 + "license": "MIT",
399 + "dependencies": {
400 + "@floating-ui/dom": "^1.7.6"
401 + },
402 + "peerDependencies": {
403 + "react": ">=16.8.0",
404 + "react-dom": ">=16.8.0"
405 + }
406 + },
407 "node_modules/@ampproject/remapping": {
408 "version": "2.3.0",
409 "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
@@ -2434,38 +2638,29 @@
2638 }
2639 },
2640 "node_modules/@floating-ui/core": {
2437 - "version": "1.6.0",
2438 - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.0.tgz",
2439 - "integrity": "sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==",
2641 + "version": "1.7.5",
2642 + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz",
2643 + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==",
2644 + "license": "MIT",
2645 "dependencies": {
2441 - "@floating-ui/utils": "^0.2.1"
2646 + "@floating-ui/utils": "^0.2.11"
2647 }
2648 },
2649 "node_modules/@floating-ui/dom": {
2445 - "version": "1.6.1",
2446 - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.1.tgz",
2447 - "integrity": "sha512-iA8qE43/H5iGozC3W0YSnVSW42Vh522yyM1gj+BqRwVsTNOyr231PsXDaV04yT39PsO0QL2QpbI/M0ZaLUQgRQ==",
2650 + "version": "1.7.6",
2651 + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz",
2652 + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
2653 + "license": "MIT",
2654 "dependencies": {
2449 - "@floating-ui/core": "^1.6.0",
2450 - "@floating-ui/utils": "^0.2.1"
2451 - }
2452 - },
2453 - "node_modules/@floating-ui/react-dom": {
2454 - "version": "2.0.8",
2455 - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.8.tgz",
2456 - "integrity": "sha512-HOdqOt3R3OGeTKidaLvJKcgg75S6tibQ3Tif4eyd91QnIJWr0NLvoXFpJA/j8HqkFSL68GDca9AuyWEHlhyClw==",
2457 - "dependencies": {
2458 - "@floating-ui/dom": "^1.6.1"
2459 - },
2460 - "peerDependencies": {
2461 - "react": ">=16.8.0",
2462 - "react-dom": ">=16.8.0"
2655 + "@floating-ui/core": "^1.7.5",
2656 + "@floating-ui/utils": "^0.2.11"
2657 }
2658 },
2659 "node_modules/@floating-ui/utils": {
2466 - "version": "0.2.1",
2467 - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz",
2468 - "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q=="
2660 + "version": "0.2.11",
2661 + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz",
2662 + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==",
2663 + "license": "MIT"
2664 },
2665 "node_modules/@gregoranders/csv": {
2666 "version": "0.0.13",
@@ -2559,137 +2754,37 @@
2754 "@jridgewell/sourcemap-codec": "^1.4.14"
2755 }
2756 },
2562 - "node_modules/@mui/base": {
2563 - "version": "5.0.0-beta.40-1",
2564 - "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.40-1.tgz",
2565 - "integrity": "sha512-agKXuNNy0bHUmeU7pNmoZwNFr7Hiyhojkb9+2PVyDG5+6RafYuyMgbrav8CndsB7KUc/U51JAw9vKNDLYBzaUA==",
2566 - "deprecated": "This package has been replaced by @base-ui-components/react",
2567 - "license": "MIT",
2568 - "dependencies": {
2569 - "@babel/runtime": "^7.23.9",
2570 - "@floating-ui/react-dom": "^2.0.8",
2571 - "@mui/types": "~7.2.15",
2572 - "@mui/utils": "^5.17.1",
2573 - "@popperjs/core": "^2.11.8",
2574 - "clsx": "^2.1.0",
2575 - "prop-types": "^15.8.1"
2576 - },
2577 - "engines": {
2578 - "node": ">=12.0.0"
2579 - },
2580 - "funding": {
2581 - "type": "opencollective",
2582 - "url": "https://opencollective.com/mui-org"
2583 - },
2584 - "peerDependencies": {
2585 - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
2586 - "react": "^17.0.0 || ^18.0.0 || ^19.0.0",
2587 - "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
2588 - },
2589 - "peerDependenciesMeta": {
2590 - "@types/react": {
2591 - "optional": true
2592 - }
2593 - }
2594 - },
2757 "node_modules/@mui/core-downloads-tracker": {
2596 - "version": "5.18.0",
2597 - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.18.0.tgz",
2598 - "integrity": "sha512-jbhwoQ1AY200PSSOrNXmrFCaSDSJWP7qk6urkTmIirvRXDROkqe+QwcLlUiw/PrREwsIF/vm3/dAXvjlMHF0RA==",
2599 - "license": "MIT",
2600 - "funding": {
2601 - "type": "opencollective",
2602 - "url": "https://opencollective.com/mui-org"
2603 - }
2604 - },
2605 - "node_modules/@mui/icons-material": {
2606 - "version": "5.18.0",
2607 - "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.18.0.tgz",
2608 - "integrity": "sha512-1s0vEZj5XFXDMmz3Arl/R7IncFqJ+WQ95LDp1roHWGDE2oCO3IS4/hmiOv1/8SD9r6B7tv9GLiqVZYHo+6PkTg==",
2609 - "license": "MIT",
2610 - "dependencies": {
2611 - "@babel/runtime": "^7.23.9"
2612 - },
2613 - "engines": {
2614 - "node": ">=12.0.0"
2615 - },
2616 - "funding": {
2617 - "type": "opencollective",
2618 - "url": "https://opencollective.com/mui-org"
2619 - },
2620 - "peerDependencies": {
2621 - "@mui/material": "^5.0.0",
2622 - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
2623 - "react": "^17.0.0 || ^18.0.0 || ^19.0.0"
2624 - },
2625 - "peerDependenciesMeta": {
2626 - "@types/react": {
2627 - "optional": true
2628 - }
2629 - }
2630 - },
2631 - "node_modules/@mui/lab": {
2632 - "version": "5.0.0-alpha.177",
2633 - "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.177.tgz",
2634 - "integrity": "sha512-bdCxxtNjlWAgN9rtrwlmFydJ1qxA3IIbb6OlomGFsIXw0zGoHomLyjvh72q/R3yUAC0kvSef18cHY1UalLylyQ==",
2758 + "version": "6.5.0",
2759 + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.5.0.tgz",
2760 + "integrity": "sha512-LGb8t8i6M2ZtS3Drn3GbTI1DVhDY6FJ9crEey2lZ0aN2EMZo8IZBZj9wRf4vqbZHaWjsYgtbOnJw5V8UWbmK2Q==",
2761 "license": "MIT",
2636 - "dependencies": {
2637 - "@babel/runtime": "^7.23.9",
2638 - "@mui/base": "5.0.0-beta.40-1",
2639 - "@mui/system": "^5.18.0",
2640 - "@mui/types": "~7.2.15",
2641 - "@mui/utils": "^5.17.1",
2642 - "clsx": "^2.1.0",
2643 - "prop-types": "^15.8.1"
2644 - },
2645 - "engines": {
2646 - "node": ">=12.0.0"
2647 - },
2762 "funding": {
2763 "type": "opencollective",
2764 "url": "https://opencollective.com/mui-org"
2651 - },
2652 - "peerDependencies": {
2653 - "@emotion/react": "^11.5.0",
2654 - "@emotion/styled": "^11.3.0",
2655 - "@mui/material": ">=5.15.0",
2656 - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
2657 - "react": "^17.0.0 || ^18.0.0 || ^19.0.0",
2658 - "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
2659 - },
2660 - "peerDependenciesMeta": {
2661 - "@emotion/react": {
2662 - "optional": true
2663 - },
2664 - "@emotion/styled": {
2665 - "optional": true
2666 - },
2667 - "@types/react": {
2668 - "optional": true
2669 - }
2765 }
2766 },
2767 "node_modules/@mui/material": {
2673 - "version": "5.18.0",
2674 - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.18.0.tgz",
2675 - "integrity": "sha512-bbH/HaJZpFtXGvWg3TsBWG4eyt3gah3E7nCNU8GLyRjVoWcA91Vm/T+sjHfUcwgJSw9iLtucfHBoq+qW/T30aA==",
2768 + "version": "6.5.0",
2769 + "resolved": "https://registry.npmjs.org/@mui/material/-/material-6.5.0.tgz",
2770 + "integrity": "sha512-yjvtXoFcrPLGtgKRxFaH6OQPtcLPhkloC0BML6rBG5UeldR0nPULR/2E2BfXdo5JNV7j7lOzrrLX2Qf/iSidow==",
2771 "license": "MIT",
2772 "dependencies": {
2678 - "@babel/runtime": "^7.23.9",
2679 - "@mui/core-downloads-tracker": "^5.18.0",
2680 - "@mui/system": "^5.18.0",
2681 - "@mui/types": "~7.2.15",
2682 - "@mui/utils": "^5.17.1",
2773 + "@babel/runtime": "^7.26.0",
2774 + "@mui/core-downloads-tracker": "^6.5.0",
2775 + "@mui/system": "^6.5.0",
2776 + "@mui/types": "~7.2.24",
2777 + "@mui/utils": "^6.4.9",
2778 "@popperjs/core": "^2.11.8",
2684 - "@types/react-transition-group": "^4.4.10",
2685 - "clsx": "^2.1.0",
2779 + "@types/react-transition-group": "^4.4.12",
2780 + "clsx": "^2.1.1",
2781 "csstype": "^3.1.3",
2782 "prop-types": "^15.8.1",
2783 "react-is": "^19.0.0",
2784 "react-transition-group": "^4.4.5"
2785 },
2786 "engines": {
2692 - "node": ">=12.0.0"
2787 + "node": ">=14.0.0"
2788 },
2789 "funding": {
2790 "type": "opencollective",
@@ -2698,6 +2793,7 @@
2793 "peerDependencies": {
2794 "@emotion/react": "^11.5.0",
2795 "@emotion/styled": "^11.3.0",
2796 + "@mui/material-pigment-css": "^6.5.0",
2797 "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
2798 "react": "^17.0.0 || ^18.0.0 || ^19.0.0",
2799 "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
@@ -2709,23 +2805,26 @@
2805 "@emotion/styled": {
2806 "optional": true
2807 },
2808 + "@mui/material-pigment-css": {
2809 + "optional": true
2810 + },
2811 "@types/react": {
2812 "optional": true
2813 }
2814 }
2815 },
2816 "node_modules/@mui/private-theming": {
2718 - "version": "5.17.1",
2719 - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.17.1.tgz",
2720 - "integrity": "sha512-XMxU0NTYcKqdsG8LRmSoxERPXwMbp16sIXPcLVgLGII/bVNagX0xaheWAwFv8+zDK7tI3ajllkuD3GZZE++ICQ==",
2817 + "version": "6.4.9",
2818 + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.4.9.tgz",
2819 + "integrity": "sha512-LktcVmI5X17/Q5SkwjCcdOLBzt1hXuc14jYa7NPShog0GBDCDvKtcnP0V7a2s6EiVRlv7BzbWEJzH6+l/zaCxw==",
2820 "license": "MIT",
2821 "dependencies": {
2723 - "@babel/runtime": "^7.23.9",
2724 - "@mui/utils": "^5.17.1",
2822 + "@babel/runtime": "^7.26.0",
2823 + "@mui/utils": "^6.4.9",
2824 "prop-types": "^15.8.1"
2825 },
2826 "engines": {
2728 - "node": ">=12.0.0"
2827 + "node": ">=14.0.0"
2828 },
2829 "funding": {
2830 "type": "opencollective",
@@ -2742,19 +2841,20 @@
2841 }
2842 },
2843 "node_modules/@mui/styled-engine": {
2745 - "version": "5.18.0",
2746 - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.18.0.tgz",
2747 - "integrity": "sha512-BN/vKV/O6uaQh2z5rXV+MBlVrEkwoS/TK75rFQ2mjxA7+NBo8qtTAOA4UaM0XeJfn7kh2wZ+xQw2HAx0u+TiBg==",
2844 + "version": "6.5.0",
2845 + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.5.0.tgz",
2846 + "integrity": "sha512-8woC2zAqF4qUDSPIBZ8v3sakj+WgweolpyM/FXf8jAx6FMls+IE4Y8VDZc+zS805J7PRz31vz73n2SovKGaYgw==",
2847 "license": "MIT",
2848 "dependencies": {
2750 - "@babel/runtime": "^7.23.9",
2849 + "@babel/runtime": "^7.26.0",
2850 "@emotion/cache": "^11.13.5",
2851 "@emotion/serialize": "^1.3.3",
2852 + "@emotion/sheet": "^1.4.0",
2853 "csstype": "^3.1.3",
2854 "prop-types": "^15.8.1"
2855 },
2856 "engines": {
2757 - "node": ">=12.0.0"
2857 + "node": ">=14.0.0"
2858 },
2859 "funding": {
2860 "type": "opencollective",
@@ -2775,22 +2875,22 @@
2875 }
2876 },
2877 "node_modules/@mui/system": {
2778 - "version": "5.18.0",
2779 - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.18.0.tgz",
2780 - "integrity": "sha512-ojZGVcRWqWhu557cdO3pWHloIGJdzVtxs3rk0F9L+x55LsUjcMUVkEhiF7E4TMxZoF9MmIHGGs0ZX3FDLAf0Xw==",
2878 + "version": "6.5.0",
2879 + "resolved": "https://registry.npmjs.org/@mui/system/-/system-6.5.0.tgz",
2880 + "integrity": "sha512-XcbBYxDS+h/lgsoGe78ExXFZXtuIlSBpn/KsZq8PtZcIkUNJInkuDqcLd2rVBQrDC1u+rvVovdaWPf2FHKJf3w==",
2881 "license": "MIT",
2882 "dependencies": {
2783 - "@babel/runtime": "^7.23.9",
2784 - "@mui/private-theming": "^5.17.1",
2785 - "@mui/styled-engine": "^5.18.0",
2786 - "@mui/types": "~7.2.15",
2787 - "@mui/utils": "^5.17.1",
2788 - "clsx": "^2.1.0",
2883 + "@babel/runtime": "^7.26.0",
2884 + "@mui/private-theming": "^6.4.9",
2885 + "@mui/styled-engine": "^6.5.0",
2886 + "@mui/types": "~7.2.24",
2887 + "@mui/utils": "^6.4.9",
2888 + "clsx": "^2.1.1",
2889 "csstype": "^3.1.3",
2890 "prop-types": "^15.8.1"
2891 },
2892 "engines": {
2793 - "node": ">=12.0.0"
2893 + "node": ">=14.0.0"
2894 },
2895 "funding": {
2896 "type": "opencollective",
@@ -2815,9 +2915,10 @@
2915 }
2916 },
2917 "node_modules/@mui/types": {
2818 - "version": "7.2.16",
2819 - "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.16.tgz",
2820 - "integrity": "sha512-qI8TV3M7ShITEEc8Ih15A2vLzZGLhD+/UPNwck/hcls2gwg7dyRjNGXcQYHKLB5Q7PuTRfrTkAoPa2VV1s67Ag==",
2918 + "version": "7.2.24",
2919 + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.24.tgz",
2920 + "integrity": "sha512-3c8tRt/CbWZ+pEg7QpSwbdxOk36EfmhbKf6AGZsD1EcLDLTSZoxxJ86FVtcjxvjuhdyBiWKSTGZFaXCnidO2kw==",
2921 + "license": "MIT",
2922 "peerDependencies": {
2923 "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0"
2924 },
@@ -2828,20 +2929,20 @@
2929 }
2930 },
2931 "node_modules/@mui/utils": {
2831 - "version": "5.17.1",
2832 - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.17.1.tgz",
2833 - "integrity": "sha512-jEZ8FTqInt2WzxDV8bhImWBqeQRD99c/id/fq83H0ER9tFl+sfZlaAoCdznGvbSQQ9ividMxqSV2c7cC1vBcQg==",
2932 + "version": "6.4.9",
2933 + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.4.9.tgz",
2934 + "integrity": "sha512-Y12Q9hbK9g+ZY0T3Rxrx9m2m10gaphDuUMgWxyV5kNJevVxXYCLclYUCC9vXaIk1/NdNDTcW2Yfr2OGvNFNmHg==",
2935 "license": "MIT",
2936 "dependencies": {
2836 - "@babel/runtime": "^7.23.9",
2837 - "@mui/types": "~7.2.15",
2838 - "@types/prop-types": "^15.7.12",
2937 + "@babel/runtime": "^7.26.0",
2938 + "@mui/types": "~7.2.24",
2939 + "@types/prop-types": "^15.7.14",
2940 "clsx": "^2.1.1",
2941 "prop-types": "^15.8.1",
2942 "react-is": "^19.0.0"
2943 },
2944 "engines": {
2844 - "node": ">=12.0.0"
2945 + "node": ">=14.0.0"
2946 },
2947 "funding": {
2948 "type": "opencollective",
@@ -2857,17 +2958,55 @@
2958 }
2959 }
2960 },
2961 + "node_modules/@mui/x-data-grid": {
2962 + "version": "7.29.12",
2963 + "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-7.29.12.tgz",
2964 + "integrity": "sha512-MaEC7ubr/je8jVWjdRU7LxBXAzlOZwFEdNdvlDUJIYkRa3TRCQ1HsY8Gd8Od0jnlnMYn9M4BrEfOrq9VRnt4bw==",
2965 + "license": "MIT",
2966 + "dependencies": {
2967 + "@babel/runtime": "^7.25.7",
2968 + "@mui/utils": "^5.16.6 || ^6.0.0 || ^7.0.0",
2969 + "@mui/x-internals": "7.29.0",
2970 + "clsx": "^2.1.1",
2971 + "prop-types": "^15.8.1",
2972 + "reselect": "^5.1.1",
2973 + "use-sync-external-store": "^1.0.0"
2974 + },
2975 + "engines": {
2976 + "node": ">=14.0.0"
2977 + },
2978 + "funding": {
2979 + "type": "opencollective",
2980 + "url": "https://opencollective.com/mui-org"
2981 + },
2982 + "peerDependencies": {
2983 + "@emotion/react": "^11.9.0",
2984 + "@emotion/styled": "^11.8.1",
2985 + "@mui/material": "^5.15.14 || ^6.0.0 || ^7.0.0",
2986 + "@mui/system": "^5.15.14 || ^6.0.0 || ^7.0.0",
2987 + "react": "^17.0.0 || ^18.0.0 || ^19.0.0",
2988 + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
2989 + },
2990 + "peerDependenciesMeta": {
2991 + "@emotion/react": {
2992 + "optional": true
2993 + },
2994 + "@emotion/styled": {
2995 + "optional": true
2996 + }
2997 + }
2998 + },
2999 "node_modules/@mui/x-date-pickers": {
2861 - "version": "6.20.2",
2862 - "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-6.20.2.tgz",
2863 - "integrity": "sha512-x1jLg8R+WhvkmUETRfX2wC+xJreMii78EXKLl6r3G+ggcAZlPyt0myID1Amf6hvJb9CtR7CgUo8BwR+1Vx9Ggw==",
3000 + "version": "7.29.4",
3001 + "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-7.29.4.tgz",
3002 + "integrity": "sha512-wJ3tsqk/y6dp+mXGtT9czciAMEO5Zr3IIAHg9x6IL0Eqanqy0N3chbmQQZv3iq0m2qUpQDLvZ4utZBUTJdjNzw==",
3003 "license": "MIT",
3004 "dependencies": {
2866 - "@babel/runtime": "^7.23.2",
2867 - "@mui/base": "^5.0.0-beta.22",
2868 - "@mui/utils": "^5.14.16",
2869 - "@types/react-transition-group": "^4.4.8",
2870 - "clsx": "^2.0.0",
3005 + "@babel/runtime": "^7.25.7",
3006 + "@mui/utils": "^5.16.6 || ^6.0.0 || ^7.0.0",
3007 + "@mui/x-internals": "7.29.0",
3008 + "@types/react-transition-group": "^4.4.11",
3009 + "clsx": "^2.1.1",
3010 "prop-types": "^15.8.1",
3011 "react-transition-group": "^4.4.5"
3012 },
@@ -2876,22 +3015,22 @@
3015 },
3016 "funding": {
3017 "type": "opencollective",
2879 - "url": "https://opencollective.com/mui"
3018 + "url": "https://opencollective.com/mui-org"
3019 },
3020 "peerDependencies": {
3021 "@emotion/react": "^11.9.0",
3022 "@emotion/styled": "^11.8.1",
2884 - "@mui/material": "^5.8.6",
2885 - "@mui/system": "^5.8.0",
2886 - "date-fns": "^2.25.0 || ^3.2.0",
2887 - "date-fns-jalali": "^2.13.0-0",
3023 + "@mui/material": "^5.15.14 || ^6.0.0 || ^7.0.0",
3024 + "@mui/system": "^5.15.14 || ^6.0.0 || ^7.0.0",
3025 + "date-fns": "^2.25.0 || ^3.2.0 || ^4.0.0",
3026 + "date-fns-jalali": "^2.13.0-0 || ^3.2.0-0 || ^4.0.0-0",
3027 "dayjs": "^1.10.7",
3028 "luxon": "^3.0.2",
3029 "moment": "^2.29.4",
2891 - "moment-hijri": "^2.1.2",
3030 + "moment-hijri": "^2.1.2 || ^3.0.0",
3031 "moment-jalaali": "^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0",
2893 - "react": "^17.0.0 || ^18.0.0",
2894 - "react-dom": "^17.0.0 || ^18.0.0"
3032 + "react": "^17.0.0 || ^18.0.0 || ^19.0.0",
3033 + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
3034 },
3035 "peerDependenciesMeta": {
3036 "@emotion/react": {
@@ -2923,16 +3062,37 @@
3062 }
3063 }
3064 },
3065 + "node_modules/@mui/x-internals": {
3066 + "version": "7.29.0",
3067 + "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-7.29.0.tgz",
3068 + "integrity": "sha512-+Gk6VTZIFD70XreWvdXBwKd8GZ2FlSCuecQFzm6znwqXg1ZsndavrhG9tkxpxo2fM1Zf7Tk8+HcOO0hCbhTQFA==",
3069 + "license": "MIT",
3070 + "dependencies": {
3071 + "@babel/runtime": "^7.25.7",
3072 + "@mui/utils": "^5.16.6 || ^6.0.0 || ^7.0.0"
3073 + },
3074 + "engines": {
3075 + "node": ">=14.0.0"
3076 + },
3077 + "funding": {
3078 + "type": "opencollective",
3079 + "url": "https://opencollective.com/mui-org"
3080 + },
3081 + "peerDependencies": {
3082 + "react": "^17.0.0 || ^18.0.0 || ^19.0.0"
3083 + }
3084 + },
3085 "node_modules/@mui/x-tree-view": {
2927 - "version": "6.17.0",
2928 - "resolved": "https://registry.npmjs.org/@mui/x-tree-view/-/x-tree-view-6.17.0.tgz",
2929 - "integrity": "sha512-09dc2D+Rjg2z8KOaxbUXyPi0aw7fm2jurEtV8Xw48xJ00joLWd5QJm1/v4CarEvaiyhTQzHImNqdgeJW8ZQB6g==",
2930 - "dependencies": {
2931 - "@babel/runtime": "^7.23.2",
2932 - "@mui/base": "^5.0.0-beta.20",
2933 - "@mui/utils": "^5.14.14",
2934 - "@types/react-transition-group": "^4.4.8",
2935 - "clsx": "^2.0.0",
3086 + "version": "7.29.10",
3087 + "resolved": "https://registry.npmjs.org/@mui/x-tree-view/-/x-tree-view-7.29.10.tgz",
3088 + "integrity": "sha512-/ZcM582yIaQN2PmadIlQYRJzc3yXV7bh463J4GHtTmFw+PEjzUfzETBWe3VxmU3EPgIFzVQPjqAAJwylmQSJOg==",
3089 + "license": "MIT",
3090 + "dependencies": {
3091 + "@babel/runtime": "^7.25.7",
3092 + "@mui/utils": "^5.16.6 || ^6.0.0 || ^7.0.0",
3093 + "@mui/x-internals": "7.29.0",
3094 + "@types/react-transition-group": "^4.4.11",
3095 + "clsx": "^2.1.1",
3096 "prop-types": "^15.8.1",
3097 "react-transition-group": "^4.4.5"
3098 },
@@ -2941,15 +3101,23 @@
3101 },
3102 "funding": {
3103 "type": "opencollective",
2944 - "url": "https://opencollective.com/mui"
3104 + "url": "https://opencollective.com/mui-org"
3105 },
3106 "peerDependencies": {
3107 "@emotion/react": "^11.9.0",
3108 "@emotion/styled": "^11.8.1",
2949 - "@mui/material": "^5.8.6",
2950 - "@mui/system": "^5.8.0",
2951 - "react": "^17.0.0 || ^18.0.0",
2952 - "react-dom": "^17.0.0 || ^18.0.0"
3109 + "@mui/material": "^5.15.14 || ^6.0.0 || ^7.0.0",
3110 + "@mui/system": "^5.15.14 || ^6.0.0 || ^7.0.0",
3111 + "react": "^17.0.0 || ^18.0.0 || ^19.0.0",
3112 + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
3113 + },
3114 + "peerDependenciesMeta": {
3115 + "@emotion/react": {
3116 + "optional": true
3117 + },
3118 + "@emotion/styled": {
3119 + "optional": true
3120 + }
3121 }
3122 },
3123 "node_modules/@nodable/entities": {
@@ -3857,9 +4025,10 @@
4025 "license": "MIT"
4026 },
4027 "node_modules/@types/prop-types": {
3860 - "version": "15.7.12",
3861 - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
3862 - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q=="
4028 + "version": "15.7.15",
4029 + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
4030 + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==",
4031 + "license": "MIT"
4032 },
4033 "node_modules/@types/qs": {
4034 "version": "6.9.7",
@@ -3894,10 +4063,11 @@
4063 }
4064 },
4065 "node_modules/@types/react-transition-group": {
3897 - "version": "4.4.10",
3898 - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz",
3899 - "integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==",
3900 - "dependencies": {
4066 + "version": "4.4.12",
4067 + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz",
4068 + "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==",
4069 + "license": "MIT",
4070 + "peerDependencies": {
4071 "@types/react": "*"
4072 }
4073 },
@@ -8459,6 +8629,12 @@
8629 "node": ">=0.10.0"
8630 }
8631 },
8632 + "node_modules/reselect": {
8633 + "version": "5.1.1",
8634 + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz",
8635 + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==",
8636 + "license": "MIT"
8637 + },
8638 "node_modules/resolve": {
8639 "version": "1.22.10",
8640 "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
@@ -11241,34 +11417,26 @@
11417 "optional": true
11418 },
11419 "@floating-ui/core": {
11244 - "version": "1.6.0",
11245 - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.0.tgz",
11246 - "integrity": "sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==",
11420 + "version": "1.7.5",
11421 + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz",
11422 + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==",
11423 "requires": {
11248 - "@floating-ui/utils": "^0.2.1"
11424 + "@floating-ui/utils": "^0.2.11"
11425 }
11426 },
11427 "@floating-ui/dom": {
11252 - "version": "1.6.1",
11253 - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.1.tgz",
11254 - "integrity": "sha512-iA8qE43/H5iGozC3W0YSnVSW42Vh522yyM1gj+BqRwVsTNOyr231PsXDaV04yT39PsO0QL2QpbI/M0ZaLUQgRQ==",
11428 + "version": "1.7.6",
11429 + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz",
11430 + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
11431 "requires": {
11256 - "@floating-ui/core": "^1.6.0",
11257 - "@floating-ui/utils": "^0.2.1"
11258 - }
11259 - },
11260 - "@floating-ui/react-dom": {
11261 - "version": "2.0.8",
11262 - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.8.tgz",
11263 - "integrity": "sha512-HOdqOt3R3OGeTKidaLvJKcgg75S6tibQ3Tif4eyd91QnIJWr0NLvoXFpJA/j8HqkFSL68GDca9AuyWEHlhyClw==",
11264 - "requires": {
11265 - "@floating-ui/dom": "^1.6.1"
11432 + "@floating-ui/core": "^1.7.5",
11433 + "@floating-ui/utils": "^0.2.11"
11434 }
11435 },
11436 "@floating-ui/utils": {
11269 - "version": "0.2.1",
11270 - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz",
11271 - "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q=="
11437 + "version": "0.2.11",
11438 + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz",
11439 + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg=="
11440 },
11441 "@gregoranders/csv": {
11442 "version": "0.0.13",
@@ -11283,12 +11451,12 @@
11451 "@gregoranders/csv": "^0.0.13",
11452 "@hfs/mui-grid-form": "*",
11453 "@hfs/shared": "*",
11286 - "@mui/icons-material": "^5.18.0",
11287 - "@mui/lab": "^5.0.0-alpha.177",
11288 - "@mui/material": "^5.18.0",
11289 - "@mui/x-data-grid": "^6.20.4",
11290 - "@mui/x-date-pickers": "^6.20.2",
11291 - "@mui/x-tree-view": "^6.17.0",
11454 + "@mui/icons-material": "^6.4.11",
11455 + "@mui/lab": "^6.0.1-beta.34",
11456 + "@mui/material": "^6.4.11",
11457 + "@mui/x-data-grid": "^7.29.0",
11458 + "@mui/x-date-pickers": "^7.29.0",
11459 + "@mui/x-tree-view": "^7.29.0",
11460 "@types/prismjs": "^1.26.5",
11461 "@types/react": "^18.3.14",
11462 "@types/react-dom": "^18.3.2",
@@ -11307,22 +11475,53 @@
11475 "vite": "^6.4.1"
11476 },
11477 "dependencies": {
11310 - "@mui/x-data-grid": {
11311 - "version": "6.20.4",
11312 - "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-6.20.4.tgz",
11313 - "integrity": "sha512-I0JhinVV4e25hD2dB+R6biPBtpGeFrXf8RwlMPQbr9gUggPmPmNtWKo8Kk2PtBBMlGtdMAgHWe7PqhmucUxU1w==",
11478 + "@mui/icons-material": {
11479 + "version": "6.5.0",
11480 + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-6.5.0.tgz",
11481 + "integrity": "sha512-VPuPqXqbBPlcVSA0BmnoE4knW4/xG6Thazo8vCLWkOKusko6DtwFV6B665MMWJ9j0KFohTIf3yx2zYtYacvG1g==",
11482 "requires": {
11315 - "@babel/runtime": "^7.23.2",
11316 - "@mui/utils": "^5.14.16",
11317 - "clsx": "^2.0.0",
11318 - "prop-types": "^15.8.1",
11319 - "reselect": "^4.1.8"
11483 + "@babel/runtime": "^7.26.0"
11484 }
11485 },
11322 - "reselect": {
11323 - "version": "4.1.8",
11324 - "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz",
11325 - "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ=="
11486 + "@mui/lab": {
11487 + "version": "6.0.1-beta.36",
11488 + "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-6.0.1-beta.36.tgz",
11489 + "integrity": "sha512-af9lDmA9SZGEWF1XXk0EVBpfCITk9IKsvh9lLOZGdYaaHfQeCsqxGEDMvNO66j0P8EYoxpyry84LFCJYuLVtVw==",
11490 + "requires": {
11491 + "@babel/runtime": "^7.26.0",
11492 + "@mui/base": "5.0.0-beta.70",
11493 + "@mui/system": "^6.5.0",
11494 + "@mui/types": "~7.2.24",
11495 + "@mui/utils": "^6.4.9",
11496 + "clsx": "^2.1.1",
11497 + "prop-types": "^15.8.1"
11498 + },
11499 + "dependencies": {
11500 + "@mui/base": {
11501 + "version": "5.0.0-beta.70",
11502 + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.70.tgz",
11503 + "integrity": "sha512-Tb/BIhJzb0pa5zv/wu7OdokY9ZKEDqcu1BDFnohyvGCoHuSXbEr90rPq1qeNW3XvTBIbNWHEF7gqge+xpUo6tQ==",
11504 + "requires": {
11505 + "@babel/runtime": "^7.26.0",
11506 + "@floating-ui/react-dom": "^2.1.1",
11507 + "@mui/types": "~7.2.24",
11508 + "@mui/utils": "^6.4.8",
11509 + "@popperjs/core": "^2.11.8",
11510 + "clsx": "^2.1.1",
11511 + "prop-types": "^15.8.1"
11512 + },
11513 + "dependencies": {
11514 + "@floating-ui/react-dom": {
11515 + "version": "2.1.8",
11516 + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz",
11517 + "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==",
11518 + "requires": {
11519 + "@floating-ui/dom": "^1.7.6"
11520 + }
11521 + }
11522 + }
11523 + }
11524 + }
11525 }
11526 }
11527 },
@@ -11375,6 +11574,56 @@
11574 "lodash": "*",
11575 "react": "*",
11576 "react-dom": "*"
11577 + },
11578 + "dependencies": {
11579 + "@mui/icons-material": {
11580 + "version": "6.5.0",
11581 + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-6.5.0.tgz",
11582 + "integrity": "sha512-VPuPqXqbBPlcVSA0BmnoE4knW4/xG6Thazo8vCLWkOKusko6DtwFV6B665MMWJ9j0KFohTIf3yx2zYtYacvG1g==",
11583 + "requires": {
11584 + "@babel/runtime": "^7.26.0"
11585 + }
11586 + },
11587 + "@mui/lab": {
11588 + "version": "6.0.1-beta.36",
11589 + "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-6.0.1-beta.36.tgz",
11590 + "integrity": "sha512-af9lDmA9SZGEWF1XXk0EVBpfCITk9IKsvh9lLOZGdYaaHfQeCsqxGEDMvNO66j0P8EYoxpyry84LFCJYuLVtVw==",
11591 + "requires": {
11592 + "@babel/runtime": "^7.26.0",
11593 + "@mui/base": "5.0.0-beta.70",
11594 + "@mui/system": "^6.5.0",
11595 + "@mui/types": "~7.2.24",
11596 + "@mui/utils": "^6.4.9",
11597 + "clsx": "^2.1.1",
11598 + "prop-types": "^15.8.1"
11599 + },
11600 + "dependencies": {
11601 + "@mui/base": {
11602 + "version": "5.0.0-beta.70",
11603 + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.70.tgz",
11604 + "integrity": "sha512-Tb/BIhJzb0pa5zv/wu7OdokY9ZKEDqcu1BDFnohyvGCoHuSXbEr90rPq1qeNW3XvTBIbNWHEF7gqge+xpUo6tQ==",
11605 + "requires": {
11606 + "@babel/runtime": "^7.26.0",
11607 + "@floating-ui/react-dom": "^2.1.1",
11608 + "@mui/types": "~7.2.24",
11609 + "@mui/utils": "^6.4.8",
11610 + "@popperjs/core": "^2.11.8",
11611 + "clsx": "^2.1.1",
11612 + "prop-types": "^15.8.1"
11613 + },
11614 + "dependencies": {
11615 + "@floating-ui/react-dom": {
11616 + "version": "2.1.8",
11617 + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz",
11618 + "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==",
11619 + "requires": {
11620 + "@floating-ui/dom": "^1.7.6"
11621 + }
11622 + }
11623 + }
11624 + }
11625 + }
11626 + }
11627 }
11628 },
11629 "@hfs/shared": {
@@ -11444,60 +11693,24 @@
11693 "@jridgewell/sourcemap-codec": "^1.4.14"
11694 }
11695 },
11447 - "@mui/base": {
11448 - "version": "5.0.0-beta.40-1",
11449 - "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.40-1.tgz",
11450 - "integrity": "sha512-agKXuNNy0bHUmeU7pNmoZwNFr7Hiyhojkb9+2PVyDG5+6RafYuyMgbrav8CndsB7KUc/U51JAw9vKNDLYBzaUA==",
11451 - "requires": {
11452 - "@babel/runtime": "^7.23.9",
11453 - "@floating-ui/react-dom": "^2.0.8",
11454 - "@mui/types": "~7.2.15",
11455 - "@mui/utils": "^5.17.1",
11456 - "@popperjs/core": "^2.11.8",
11457 - "clsx": "^2.1.0",
11458 - "prop-types": "^15.8.1"
11459 - }
11460 - },
11696 "@mui/core-downloads-tracker": {
11462 - "version": "5.18.0",
11463 - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.18.0.tgz",
11464 - "integrity": "sha512-jbhwoQ1AY200PSSOrNXmrFCaSDSJWP7qk6urkTmIirvRXDROkqe+QwcLlUiw/PrREwsIF/vm3/dAXvjlMHF0RA=="
11465 - },
11466 - "@mui/icons-material": {
11467 - "version": "5.18.0",
11468 - "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.18.0.tgz",
11469 - "integrity": "sha512-1s0vEZj5XFXDMmz3Arl/R7IncFqJ+WQ95LDp1roHWGDE2oCO3IS4/hmiOv1/8SD9r6B7tv9GLiqVZYHo+6PkTg==",
11470 - "requires": {
11471 - "@babel/runtime": "^7.23.9"
11472 - }
11473 - },
11474 - "@mui/lab": {
11475 - "version": "5.0.0-alpha.177",
11476 - "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.177.tgz",
11477 - "integrity": "sha512-bdCxxtNjlWAgN9rtrwlmFydJ1qxA3IIbb6OlomGFsIXw0zGoHomLyjvh72q/R3yUAC0kvSef18cHY1UalLylyQ==",
11478 - "requires": {
11479 - "@babel/runtime": "^7.23.9",
11480 - "@mui/base": "5.0.0-beta.40-1",
11481 - "@mui/system": "^5.18.0",
11482 - "@mui/types": "~7.2.15",
11483 - "@mui/utils": "^5.17.1",
11484 - "clsx": "^2.1.0",
11485 - "prop-types": "^15.8.1"
11486 - }
11697 + "version": "6.5.0",
11698 + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.5.0.tgz",
11699 + "integrity": "sha512-LGb8t8i6M2ZtS3Drn3GbTI1DVhDY6FJ9crEey2lZ0aN2EMZo8IZBZj9wRf4vqbZHaWjsYgtbOnJw5V8UWbmK2Q=="
11700 },
11701 "@mui/material": {
11489 - "version": "5.18.0",
11490 - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.18.0.tgz",
11491 - "integrity": "sha512-bbH/HaJZpFtXGvWg3TsBWG4eyt3gah3E7nCNU8GLyRjVoWcA91Vm/T+sjHfUcwgJSw9iLtucfHBoq+qW/T30aA==",
11492 - "requires": {
11493 - "@babel/runtime": "^7.23.9",
11494 - "@mui/core-downloads-tracker": "^5.18.0",
11495 - "@mui/system": "^5.18.0",
11496 - "@mui/types": "~7.2.15",
11497 - "@mui/utils": "^5.17.1",
11702 + "version": "6.5.0",
11703 + "resolved": "https://registry.npmjs.org/@mui/material/-/material-6.5.0.tgz",
11704 + "integrity": "sha512-yjvtXoFcrPLGtgKRxFaH6OQPtcLPhkloC0BML6rBG5UeldR0nPULR/2E2BfXdo5JNV7j7lOzrrLX2Qf/iSidow==",
11705 + "requires": {
11706 + "@babel/runtime": "^7.26.0",
11707 + "@mui/core-downloads-tracker": "^6.5.0",
11708 + "@mui/system": "^6.5.0",
11709 + "@mui/types": "~7.2.24",
11710 + "@mui/utils": "^6.4.9",
11711 "@popperjs/core": "^2.11.8",
11499 - "@types/react-transition-group": "^4.4.10",
11500 - "clsx": "^2.1.0",
11712 + "@types/react-transition-group": "^4.4.12",
11713 + "clsx": "^2.1.1",
11714 "csstype": "^3.1.3",
11715 "prop-types": "^15.8.1",
11716 "react-is": "^19.0.0",
@@ -11505,85 +11718,109 @@
11718 }
11719 },
11720 "@mui/private-theming": {
11508 - "version": "5.17.1",
11509 - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.17.1.tgz",
11510 - "integrity": "sha512-XMxU0NTYcKqdsG8LRmSoxERPXwMbp16sIXPcLVgLGII/bVNagX0xaheWAwFv8+zDK7tI3ajllkuD3GZZE++ICQ==",
11721 + "version": "6.4.9",
11722 + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.4.9.tgz",
11723 + "integrity": "sha512-LktcVmI5X17/Q5SkwjCcdOLBzt1hXuc14jYa7NPShog0GBDCDvKtcnP0V7a2s6EiVRlv7BzbWEJzH6+l/zaCxw==",
11724 "requires": {
11512 - "@babel/runtime": "^7.23.9",
11513 - "@mui/utils": "^5.17.1",
11725 + "@babel/runtime": "^7.26.0",
11726 + "@mui/utils": "^6.4.9",
11727 "prop-types": "^15.8.1"
11728 }
11729 },
11730 "@mui/styled-engine": {
11518 - "version": "5.18.0",
11519 - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.18.0.tgz",
11520 - "integrity": "sha512-BN/vKV/O6uaQh2z5rXV+MBlVrEkwoS/TK75rFQ2mjxA7+NBo8qtTAOA4UaM0XeJfn7kh2wZ+xQw2HAx0u+TiBg==",
11731 + "version": "6.5.0",
11732 + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.5.0.tgz",
11733 + "integrity": "sha512-8woC2zAqF4qUDSPIBZ8v3sakj+WgweolpyM/FXf8jAx6FMls+IE4Y8VDZc+zS805J7PRz31vz73n2SovKGaYgw==",
11734 "requires": {
11522 - "@babel/runtime": "^7.23.9",
11735 + "@babel/runtime": "^7.26.0",
11736 "@emotion/cache": "^11.13.5",
11737 "@emotion/serialize": "^1.3.3",
11738 + "@emotion/sheet": "^1.4.0",
11739 "csstype": "^3.1.3",
11740 "prop-types": "^15.8.1"
11741 }
11742 },
11743 "@mui/system": {
11530 - "version": "5.18.0",
11531 - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.18.0.tgz",
11532 - "integrity": "sha512-ojZGVcRWqWhu557cdO3pWHloIGJdzVtxs3rk0F9L+x55LsUjcMUVkEhiF7E4TMxZoF9MmIHGGs0ZX3FDLAf0Xw==",
11533 - "requires": {
11534 - "@babel/runtime": "^7.23.9",
11535 - "@mui/private-theming": "^5.17.1",
11536 - "@mui/styled-engine": "^5.18.0",
11537 - "@mui/types": "~7.2.15",
11538 - "@mui/utils": "^5.17.1",
11539 - "clsx": "^2.1.0",
11744 + "version": "6.5.0",
11745 + "resolved": "https://registry.npmjs.org/@mui/system/-/system-6.5.0.tgz",
11746 + "integrity": "sha512-XcbBYxDS+h/lgsoGe78ExXFZXtuIlSBpn/KsZq8PtZcIkUNJInkuDqcLd2rVBQrDC1u+rvVovdaWPf2FHKJf3w==",
11747 + "requires": {
11748 + "@babel/runtime": "^7.26.0",
11749 + "@mui/private-theming": "^6.4.9",
11750 + "@mui/styled-engine": "^6.5.0",
11751 + "@mui/types": "~7.2.24",
11752 + "@mui/utils": "^6.4.9",
11753 + "clsx": "^2.1.1",
11754 "csstype": "^3.1.3",
11755 "prop-types": "^15.8.1"
11756 }
11757 },
11758 "@mui/types": {
11545 - "version": "7.2.16",
11546 - "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.16.tgz",
11547 - "integrity": "sha512-qI8TV3M7ShITEEc8Ih15A2vLzZGLhD+/UPNwck/hcls2gwg7dyRjNGXcQYHKLB5Q7PuTRfrTkAoPa2VV1s67Ag==",
11759 + "version": "7.2.24",
11760 + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.24.tgz",
11761 + "integrity": "sha512-3c8tRt/CbWZ+pEg7QpSwbdxOk36EfmhbKf6AGZsD1EcLDLTSZoxxJ86FVtcjxvjuhdyBiWKSTGZFaXCnidO2kw==",
11762 "requires": {}
11763 },
11764 "@mui/utils": {
11551 - "version": "5.17.1",
11552 - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.17.1.tgz",
11553 - "integrity": "sha512-jEZ8FTqInt2WzxDV8bhImWBqeQRD99c/id/fq83H0ER9tFl+sfZlaAoCdznGvbSQQ9ividMxqSV2c7cC1vBcQg==",
11765 + "version": "6.4.9",
11766 + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.4.9.tgz",
11767 + "integrity": "sha512-Y12Q9hbK9g+ZY0T3Rxrx9m2m10gaphDuUMgWxyV5kNJevVxXYCLclYUCC9vXaIk1/NdNDTcW2Yfr2OGvNFNmHg==",
11768 "requires": {
11555 - "@babel/runtime": "^7.23.9",
11556 - "@mui/types": "~7.2.15",
11557 - "@types/prop-types": "^15.7.12",
11769 + "@babel/runtime": "^7.26.0",
11770 + "@mui/types": "~7.2.24",
11771 + "@types/prop-types": "^15.7.14",
11772 "clsx": "^2.1.1",
11773 "prop-types": "^15.8.1",
11774 "react-is": "^19.0.0"
11775 }
11776 },
11777 + "@mui/x-data-grid": {
11778 + "version": "7.29.12",
11779 + "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-7.29.12.tgz",
11780 + "integrity": "sha512-MaEC7ubr/je8jVWjdRU7LxBXAzlOZwFEdNdvlDUJIYkRa3TRCQ1HsY8Gd8Od0jnlnMYn9M4BrEfOrq9VRnt4bw==",
11781 + "requires": {
11782 + "@babel/runtime": "^7.25.7",
11783 + "@mui/utils": "^5.16.6 || ^6.0.0 || ^7.0.0",
11784 + "@mui/x-internals": "7.29.0",
11785 + "clsx": "^2.1.1",
11786 + "prop-types": "^15.8.1",
11787 + "reselect": "^5.1.1",
11788 + "use-sync-external-store": "^1.0.0"
11789 + }
11790 + },
11791 "@mui/x-date-pickers": {
11564 - "version": "6.20.2",
11565 - "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-6.20.2.tgz",
11566 - "integrity": "sha512-x1jLg8R+WhvkmUETRfX2wC+xJreMii78EXKLl6r3G+ggcAZlPyt0myID1Amf6hvJb9CtR7CgUo8BwR+1Vx9Ggw==",
11567 - "requires": {
11568 - "@babel/runtime": "^7.23.2",
11569 - "@mui/base": "^5.0.0-beta.22",
11570 - "@mui/utils": "^5.14.16",
11571 - "@types/react-transition-group": "^4.4.8",
11572 - "clsx": "^2.0.0",
11792 + "version": "7.29.4",
11793 + "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-7.29.4.tgz",
11794 + "integrity": "sha512-wJ3tsqk/y6dp+mXGtT9czciAMEO5Zr3IIAHg9x6IL0Eqanqy0N3chbmQQZv3iq0m2qUpQDLvZ4utZBUTJdjNzw==",
11795 + "requires": {
11796 + "@babel/runtime": "^7.25.7",
11797 + "@mui/utils": "^5.16.6 || ^6.0.0 || ^7.0.0",
11798 + "@mui/x-internals": "7.29.0",
11799 + "@types/react-transition-group": "^4.4.11",
11800 + "clsx": "^2.1.1",
11801 "prop-types": "^15.8.1",
11802 "react-transition-group": "^4.4.5"
11803 }
11804 },
11805 + "@mui/x-internals": {
11806 + "version": "7.29.0",
11807 + "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-7.29.0.tgz",
11808 + "integrity": "sha512-+Gk6VTZIFD70XreWvdXBwKd8GZ2FlSCuecQFzm6znwqXg1ZsndavrhG9tkxpxo2fM1Zf7Tk8+HcOO0hCbhTQFA==",
11809 + "requires": {
11810 + "@babel/runtime": "^7.25.7",
11811 + "@mui/utils": "^5.16.6 || ^6.0.0 || ^7.0.0"
11812 + }
11813 + },
11814 "@mui/x-tree-view": {
11578 - "version": "6.17.0",
11579 - "resolved": "https://registry.npmjs.org/@mui/x-tree-view/-/x-tree-view-6.17.0.tgz",
11580 - "integrity": "sha512-09dc2D+Rjg2z8KOaxbUXyPi0aw7fm2jurEtV8Xw48xJ00joLWd5QJm1/v4CarEvaiyhTQzHImNqdgeJW8ZQB6g==",
11581 - "requires": {
11582 - "@babel/runtime": "^7.23.2",
11583 - "@mui/base": "^5.0.0-beta.20",
11584 - "@mui/utils": "^5.14.14",
11585 - "@types/react-transition-group": "^4.4.8",
11586 - "clsx": "^2.0.0",
11815 + "version": "7.29.10",
11816 + "resolved": "https://registry.npmjs.org/@mui/x-tree-view/-/x-tree-view-7.29.10.tgz",
11817 + "integrity": "sha512-/ZcM582yIaQN2PmadIlQYRJzc3yXV7bh463J4GHtTmFw+PEjzUfzETBWe3VxmU3EPgIFzVQPjqAAJwylmQSJOg==",
11818 + "requires": {
11819 + "@babel/runtime": "^7.25.7",
11820 + "@mui/utils": "^5.16.6 || ^6.0.0 || ^7.0.0",
11821 + "@mui/x-internals": "7.29.0",
11822 + "@types/react-transition-group": "^4.4.11",
11823 + "clsx": "^2.1.1",
11824 "prop-types": "^15.8.1",
11825 "react-transition-group": "^4.4.5"
11826 }
@@ -12237,9 +12474,9 @@
12474 "dev": true
12475 },
12476 "@types/prop-types": {
12240 - "version": "15.7.12",
12241 - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
12242 - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q=="
12477 + "version": "15.7.15",
12478 + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
12479 + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw=="
12480 },
12481 "@types/qs": {
12482 "version": "6.9.7",
@@ -12272,12 +12509,10 @@
12509 }
12510 },
12511 "@types/react-transition-group": {
12275 - "version": "4.4.10",
12276 - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz",
12277 - "integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==",
12278 - "requires": {
12279 - "@types/react": "*"
12280 - }
12512 + "version": "4.4.12",
12513 + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz",
12514 + "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==",
12515 + "requires": {}
12516 },
12517 "@types/react-window": {
12518 "version": "1.8.8",
@@ -15279,6 +15514,11 @@
15514 "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
15515 "dev": true
15516 },
15517 + "reselect": {
15518 + "version": "5.1.1",
15519 + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz",
15520 + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w=="
15521 + },
15522 "resolve": {
15523 "version": "1.22.10",
15524 "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",