From 2ac8d3b4adf53e6ff417d27a303974c37134cecd Mon Sep 17 00:00:00 2001 From: mnajdova Date: Fri, 18 Oct 2024 13:53:55 +0200 Subject: [PATCH 01/17] [docs-infra] Add recursively the relative modules in the demos --- .../components/autocomplete/testFile.js | 3 + .../components/autocomplete/top100Films.js | 4 +- packages/markdown/loader.js | 88 +++++++++++++++---- 3 files changed, 79 insertions(+), 16 deletions(-) create mode 100644 docs/data/material/components/autocomplete/testFile.js diff --git a/docs/data/material/components/autocomplete/testFile.js b/docs/data/material/components/autocomplete/testFile.js new file mode 100644 index 00000000000000..f1bb7a9b90f764 --- /dev/null +++ b/docs/data/material/components/autocomplete/testFile.js @@ -0,0 +1,3 @@ +const movies = [{ label: 'Monty Python and the Holy Grail', year: 1975 }]; + +export default movies; diff --git a/docs/data/material/components/autocomplete/top100Films.js b/docs/data/material/components/autocomplete/top100Films.js index 3226dcbc8ba7f3..7202dbd0d32e5b 100644 --- a/docs/data/material/components/autocomplete/top100Films.js +++ b/docs/data/material/components/autocomplete/top100Films.js @@ -1,3 +1,5 @@ +import movies from './testFile'; + // Top 100 films as rated by IMDb users. http://www.imdb.com/chart/top const top100Films = [ { label: 'The Shawshank Redemption', year: 1994 }, @@ -123,7 +125,7 @@ const top100Films = [ { label: 'Inglourious Basterds', year: 2009 }, { label: 'Snatch', year: 2000 }, { label: '3 Idiots', year: 2009 }, - { label: 'Monty Python and the Holy Grail', year: 1975 }, + ...movies, ]; export default top100Films; diff --git a/packages/markdown/loader.js b/packages/markdown/loader.js index 62a90a2fda9d7e..c3d3eb97f551c7 100644 --- a/packages/markdown/loader.js +++ b/packages/markdown/loader.js @@ -200,6 +200,29 @@ module.exports = async function demoLoader() { } } + /** + * @param { module: './top100Films.js', raw: '...' } moduleData + * @param string demoName + * @param ['JS' | 'TS'] variants + * Adds the relative module to the demo's relativeModules object for each of the variants + */ + function addToRelativeModules(moduleData, demoName, variants) { + variants.forEach((variant) => { + if (demos[demoName].relativeModules[variant]) { + // Avoid duplicates + if ( + !demos[demoName].relativeModules[variant].some( + (elem) => elem.module === moduleData.module, + ) + ) { + demos[demoName].relativeModules[variant].push(moduleData); + } + } else { + demos[demoName].relativeModules[variant] = [moduleData]; + } + }); + } + await Promise.all( demoNames.map(async (demoName) => { const multipleDemoVersionsUsed = !demoName.endsWith('.js'); @@ -441,29 +464,64 @@ module.exports = async function demoLoader() { await Promise.all( Array.from(relativeModules.get(demoName)).map(async ([relativeModuleID, variants]) => { let raw = ''; + const relativeModuleFilePath = path.join( + path.dirname(moduleFilepath), + relativeModuleID, + ); + try { - raw = await fs.readFile(path.join(path.dirname(moduleFilepath), relativeModuleID), { + raw = await fs.readFile(relativeModuleFilePath, { encoding: 'utf8', }); + + const importedProcessedModuleIDs = new Set(); + // Find the relative paths in the relative module + if (relativeModuleID.startsWith('.')) { + extractImports(raw).forEach((importModuleID) => { + // detect relative import + detectRelativeImports( + importModuleID, + relativeModuleFilePath, + 'JS', + importModuleID, + ); + if (importModuleID.startsWith('.')) { + importedProcessedModuleIDs.add(importModuleID); + } + }); + + const moduleData = { module: relativeModuleID, raw }; + addToRelativeModules(moduleData, demoName, variants); + } + + // iterate recursively over the relative imports + while (importedProcessedModuleIDs.size > 0) { + for (const entry of importedProcessedModuleIDs) { + if (entry.startsWith('.')) { + const entryModuleFilePath = path.join( + path.dirname(moduleFilepath), + entry + '.js', + ); + const raw = await fs.readFile(entryModuleFilePath, { encoding: 'utf8' }); + + extractImports(raw).forEach((importModuleID) => { + // detect relative import + detectRelativeImports(entry, entryModuleFilePath, 'JS', importModuleID); + if (importModuleID.startsWith('.')) { + importedProcessedModuleIDs.add(importModuleID); + } + }); + const moduleData = { module: entry + '.js', raw }; + addToRelativeModules(moduleData, demoName, variants); + } + importedProcessedModuleIDs.delete(entry); + } + } } catch { throw new Error( `Could not find a module for the relative import "${relativeModuleID}" in the demo "${demoName}"`, ); } - - const moduleData = { module: relativeModuleID, raw }; - const modules = demos[demoName].relativeModules; - - variants.forEach((variant) => { - if (modules[variant]) { - // Avoid duplicates - if (!modules[variant].some((elem) => elem.module === relativeModuleID)) { - modules[variant].push(moduleData); - } - } else { - modules[variant] = [moduleData]; - } - }); }), ); } From f688c35d3d6b5c5d5d27c0b1ce48ae5ef3e7491a Mon Sep 17 00:00:00 2001 From: mnajdova Date: Fri, 18 Oct 2024 14:56:30 +0200 Subject: [PATCH 02/17] add DataGrid demo for testing --- .../components/autocomplete/ListView.js | 107 +++++ .../components/autocomplete/ListView.tsx | 113 ++++++ .../autocomplete/ListViewAdvanced.js | 355 +++++++++++++++++ .../autocomplete/ListViewAdvanced.tsx | 375 ++++++++++++++++++ .../components/autocomplete/autocomplete.md | 6 + .../autocomplete/components/ActionDrawer.js | 88 ++++ .../autocomplete/components/ActionDrawer.tsx | 101 +++++ .../autocomplete/components/Card.js | 70 ++++ .../autocomplete/components/Card.tsx | 70 ++++ .../autocomplete/components/DetailsDrawer.js | 142 +++++++ .../autocomplete/components/DetailsDrawer.tsx | 158 ++++++++ .../autocomplete/components/Drawer.js | 88 ++++ .../autocomplete/components/Drawer.tsx | 97 +++++ .../autocomplete/components/FileIcon.js | 47 +++ .../autocomplete/components/FileIcon.tsx | 54 +++ .../autocomplete/components/ListCell.js | 110 +++++ .../autocomplete/components/ListCell.tsx | 117 ++++++ .../autocomplete/components/RenameDialog.js | 58 +++ .../autocomplete/components/RenameDialog.tsx | 67 ++++ .../autocomplete/components/Toolbar.js | 105 +++++ .../autocomplete/components/Toolbar.tsx | 115 ++++++ .../autocomplete/components/ToolbarAddItem.js | 75 ++++ .../components/ToolbarAddItem.tsx | 81 ++++ .../autocomplete/components/ToolbarButton.js | 7 + .../autocomplete/components/ToolbarButton.tsx | 8 + .../components/ToolbarColumnsItem.js | 78 ++++ .../components/ToolbarColumnsItem.tsx | 83 ++++ .../components/ToolbarDensityItem.js | 87 ++++ .../components/ToolbarDensityItem.tsx | 94 +++++ .../components/ToolbarFilterItem.js | 217 ++++++++++ .../components/ToolbarFilterItem.tsx | 225 +++++++++++ .../components/ToolbarSortItem.js | 93 +++++ .../components/ToolbarSortItem.tsx | 99 +++++ .../components/autocomplete/constants.js | 15 + .../components/autocomplete/constants.ts | 17 + .../material/components/autocomplete/data.js | 202 ++++++++++ .../material/components/autocomplete/data.ts | 204 ++++++++++ .../components/autocomplete/testFile.js | 3 - .../components/autocomplete/top100Films.js | 4 +- .../material/components/autocomplete/types.ts | 30 ++ .../material/components/autocomplete/utils.js | 56 +++ .../material/components/autocomplete/utils.ts | 56 +++ packages/markdown/loader.js | 43 +- 43 files changed, 4207 insertions(+), 13 deletions(-) create mode 100644 docs/data/material/components/autocomplete/ListView.js create mode 100644 docs/data/material/components/autocomplete/ListView.tsx create mode 100644 docs/data/material/components/autocomplete/ListViewAdvanced.js create mode 100644 docs/data/material/components/autocomplete/ListViewAdvanced.tsx create mode 100644 docs/data/material/components/autocomplete/components/ActionDrawer.js create mode 100644 docs/data/material/components/autocomplete/components/ActionDrawer.tsx create mode 100644 docs/data/material/components/autocomplete/components/Card.js create mode 100644 docs/data/material/components/autocomplete/components/Card.tsx create mode 100644 docs/data/material/components/autocomplete/components/DetailsDrawer.js create mode 100644 docs/data/material/components/autocomplete/components/DetailsDrawer.tsx create mode 100644 docs/data/material/components/autocomplete/components/Drawer.js create mode 100644 docs/data/material/components/autocomplete/components/Drawer.tsx create mode 100644 docs/data/material/components/autocomplete/components/FileIcon.js create mode 100644 docs/data/material/components/autocomplete/components/FileIcon.tsx create mode 100644 docs/data/material/components/autocomplete/components/ListCell.js create mode 100644 docs/data/material/components/autocomplete/components/ListCell.tsx create mode 100644 docs/data/material/components/autocomplete/components/RenameDialog.js create mode 100644 docs/data/material/components/autocomplete/components/RenameDialog.tsx create mode 100644 docs/data/material/components/autocomplete/components/Toolbar.js create mode 100644 docs/data/material/components/autocomplete/components/Toolbar.tsx create mode 100644 docs/data/material/components/autocomplete/components/ToolbarAddItem.js create mode 100644 docs/data/material/components/autocomplete/components/ToolbarAddItem.tsx create mode 100644 docs/data/material/components/autocomplete/components/ToolbarButton.js create mode 100644 docs/data/material/components/autocomplete/components/ToolbarButton.tsx create mode 100644 docs/data/material/components/autocomplete/components/ToolbarColumnsItem.js create mode 100644 docs/data/material/components/autocomplete/components/ToolbarColumnsItem.tsx create mode 100644 docs/data/material/components/autocomplete/components/ToolbarDensityItem.js create mode 100644 docs/data/material/components/autocomplete/components/ToolbarDensityItem.tsx create mode 100644 docs/data/material/components/autocomplete/components/ToolbarFilterItem.js create mode 100644 docs/data/material/components/autocomplete/components/ToolbarFilterItem.tsx create mode 100644 docs/data/material/components/autocomplete/components/ToolbarSortItem.js create mode 100644 docs/data/material/components/autocomplete/components/ToolbarSortItem.tsx create mode 100644 docs/data/material/components/autocomplete/constants.js create mode 100644 docs/data/material/components/autocomplete/constants.ts create mode 100644 docs/data/material/components/autocomplete/data.js create mode 100644 docs/data/material/components/autocomplete/data.ts delete mode 100644 docs/data/material/components/autocomplete/testFile.js create mode 100644 docs/data/material/components/autocomplete/types.ts create mode 100644 docs/data/material/components/autocomplete/utils.js create mode 100644 docs/data/material/components/autocomplete/utils.ts diff --git a/docs/data/material/components/autocomplete/ListView.js b/docs/data/material/components/autocomplete/ListView.js new file mode 100644 index 00000000000000..a7ab930852afeb --- /dev/null +++ b/docs/data/material/components/autocomplete/ListView.js @@ -0,0 +1,107 @@ +import * as React from 'react'; +import { DataGridPro } from '@mui/x-data-grid-pro'; +import Box from '@mui/material/Box'; +import { useDemoData } from '@mui/x-data-grid-generator'; +import Stack from '@mui/material/Stack'; +import Avatar from '@mui/material/Avatar'; +import Typography from '@mui/material/Typography'; +import Checkbox from '@mui/material/Checkbox'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import IconButton from '@mui/material/IconButton'; +import MessageIcon from '@mui/icons-material/Message'; + +function MessageAction(params) { + const handleMessage = () => { + console.log(`send message to ${params.row.phone}`); + }; + return ( + + + + ); +} + +function ListViewCell(params) { + return ( + + + + + {params.row.name} + + + {params.row.position} + + + + + ); +} + +const listColDef = { + field: 'listColumn', + renderCell: ListViewCell, +}; + +const VISIBLE_FIELDS = ['avatar', 'name', 'position']; + +export default function ListView() { + const [isListView, setIsListView] = React.useState(true); + + const { data } = useDemoData({ + dataSet: 'Employee', + rowLength: 20, + visibleFields: VISIBLE_FIELDS, + }); + + const columns = React.useMemo(() => { + return [ + ...data.columns, + { + type: 'actions', + field: 'actions', + width: 75, + getActions: (params) => [], + }, + ]; + }, [data.columns]); + + const rowHeight = isListView ? 64 : 52; + + return ( + + setIsListView(event.target.checked)} + /> + } + label="Enable list view" + /> + + + + + ); +} diff --git a/docs/data/material/components/autocomplete/ListView.tsx b/docs/data/material/components/autocomplete/ListView.tsx new file mode 100644 index 00000000000000..40239d5a8e41af --- /dev/null +++ b/docs/data/material/components/autocomplete/ListView.tsx @@ -0,0 +1,113 @@ +import * as React from 'react'; +import { + DataGridPro, + GridRenderCellParams, + GridListColDef, + GridColDef, + GridRowParams, +} from '@mui/x-data-grid-pro'; +import Box from '@mui/material/Box'; +import { useDemoData } from '@mui/x-data-grid-generator'; +import Stack from '@mui/material/Stack'; +import Avatar from '@mui/material/Avatar'; +import Typography from '@mui/material/Typography'; +import Checkbox from '@mui/material/Checkbox'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import IconButton from '@mui/material/IconButton'; +import MessageIcon from '@mui/icons-material/Message'; + +function MessageAction(params: Pick) { + const handleMessage = () => { + console.log(`send message to ${params.row.phone}`); + }; + return ( + + + + ); +} + +function ListViewCell(params: GridRenderCellParams) { + return ( + + + + + {params.row.name} + + + {params.row.position} + + + + + ); +} + +const listColDef: GridListColDef = { + field: 'listColumn', + renderCell: ListViewCell, +}; + +const VISIBLE_FIELDS = ['avatar', 'name', 'position']; + +export default function ListView() { + const [isListView, setIsListView] = React.useState(true); + + const { data } = useDemoData({ + dataSet: 'Employee', + rowLength: 20, + visibleFields: VISIBLE_FIELDS, + }); + + const columns: GridColDef[] = React.useMemo(() => { + return [ + ...data.columns, + { + type: 'actions', + field: 'actions', + width: 75, + getActions: (params) => [], + }, + ]; + }, [data.columns]); + + const rowHeight = isListView ? 64 : 52; + + return ( + + setIsListView(event.target.checked)} + /> + } + label="Enable list view" + /> + + + + + ); +} diff --git a/docs/data/material/components/autocomplete/ListViewAdvanced.js b/docs/data/material/components/autocomplete/ListViewAdvanced.js new file mode 100644 index 00000000000000..b27633b6327087 --- /dev/null +++ b/docs/data/material/components/autocomplete/ListViewAdvanced.js @@ -0,0 +1,355 @@ +import * as React from 'react'; +import { + GridActionsCellItem, + useGridApiRef, + DataGridPremium, + gridClasses, +} from '@mui/x-data-grid-premium'; +import EditIcon from '@mui/icons-material/Edit'; +import DeleteIcon from '@mui/icons-material/Delete'; +import Avatar from '@mui/material/Avatar'; +import Stack from '@mui/material/Stack'; +import OpenIcon from '@mui/icons-material/Visibility'; +import useMediaQuery from '@mui/material/useMediaQuery'; +import CSSBaseline from '@mui/material/CssBaseline'; +import { randomId } from '@mui/x-data-grid-generator'; +import { FileIcon } from './components/FileIcon'; +import { DetailsDrawer } from './components/DetailsDrawer'; +import { ListCell } from './components/ListCell'; +import { Toolbar } from './components/Toolbar'; +import { INITIAL_ROWS } from './data'; +import { FILE_TYPES } from './constants'; + +import { formatDate, formatSize, stringAvatar } from './utils'; +import { ActionDrawer } from './components/ActionDrawer'; +import { RenameDialog } from './components/RenameDialog'; + +export default function ListViewAdvanced() { + // This is used only for the example - renders the drawer inside the container + const containerRef = React.useRef(null); + const container = () => containerRef.current; + + const isListView = useMediaQuery('(min-width: 700px)'); + + const apiRef = useGridApiRef(); + + const [rows, setRows] = React.useState(INITIAL_ROWS); + + const [loading, setLoading] = React.useState(false); + + const [overlayState, setOverlayState] = React.useState({ + overlay: null, + params: null, + }); + + const handleCloseOverlay = () => { + setOverlayState({ overlay: null, params: null }); + }; + + const handleDelete = React.useCallback((ids) => { + setRows((prevRows) => prevRows.filter((row) => !ids.includes(row.id))); + }, []); + + const handleUpdate = React.useCallback((id, field, value) => { + setRows((prevRows) => + prevRows.map((row) => + row.id === id + ? { ...row, [field]: value, updatedAt: new Date().toISOString() } + : row, + ), + ); + }, []); + + const handleUpload = React.useCallback((event) => { + if (!event.target.files) { + return; + } + + const file = event.target.files[0]; + const createdAt = new Date().toISOString(); + + const fileType = file.type.split('/')[1]; + + // validate file type + if (!FILE_TYPES.includes(fileType)) { + alert('Invalid file type'); + return; + } + + const row = { + id: randomId(), + name: file.name, + description: '', + type: fileType, + size: file.size, + createdBy: 'Kenan Yusuf', + createdAt, + updatedAt: createdAt, + state: 'pending', + }; + + event.target.value = ''; + + // Add temporary row + setLoading(true); + setRows((prevRows) => [...prevRows, row]); + + // Simulate server response time + const timeout = Math.floor(Math.random() * 3000) + 2000; + setTimeout(() => { + const uploadedRow = { ...row, state: 'uploaded' }; + setRows((prevRows) => + prevRows.map((r) => (r.id === row.id ? uploadedRow : r)), + ); + setOverlayState({ overlay: 'actions', params: { row } }); + setLoading(false); + }, timeout); + }, []); + + const columns = React.useMemo( + () => [ + { + field: 'name', + headerName: 'Name', + width: 350, + editable: true, + hideable: false, + renderCell: (params) => { + return ( + + + {params.value} + + ); + }, + }, + { + field: 'createdBy', + headerName: 'Owner', + width: 200, + renderCell: (params) => { + const avatarProps = stringAvatar(params.value); + return ( + + + {params.value} + + ); + }, + }, + { + field: 'createdAt', + headerName: 'Added', + type: 'date', + width: 200, + valueFormatter: formatDate, + }, + { + field: 'updatedAt', + headerName: 'Modified', + type: 'date', + width: 200, + valueFormatter: formatDate, + }, + { + field: 'type', + headerName: 'Type', + width: 150, + }, + { + field: 'size', + headerName: 'Size', + width: 120, + valueFormatter: formatSize, + }, + { + type: 'actions', + field: 'actions', + resizable: false, + width: 50, + getActions: (params) => [ + } + onClick={() => { + setOverlayState({ overlay: 'actions', params }); + }} + showInMenu + />, + } + onClick={() => + apiRef.current?.startCellEditMode({ + id: params.id, + field: 'name', + }) + } + showInMenu + />, + } + onClick={() => handleDelete([params.id])} + showInMenu + />, + ], + }, + ], + [handleDelete, apiRef], + ); + + const listColDef = React.useMemo( + () => ({ + field: 'listCell', + renderCell: (params) => ( + { + setOverlayState({ overlay: 'actions', params }); + }} + /> + ), + }), + [], + ); + + const getEstimatedRowHeight = () => { + const density = apiRef.current?.state?.density; + + if (isListView) { + switch (density) { + case 'compact': + return 47; + case 'standard': + return 67; + case 'comfortable': + return 97; + default: + return 67; + } + } else { + switch (density) { + case 'compact': + return 47; + case 'standard': + return 55; + case 'comfortable': + return 63; + default: + return 55; + } + } + }; + + const getRowHeight = React.useCallback( + () => (isListView ? 'auto' : undefined), + [isListView], + ); + + return ( + + +
+ + setOverlayState({ overlay: 'actions', params }) + } + hideFooterSelectedRowCount + /> + handleUpdate(id, 'description', value)} + onClose={handleCloseOverlay} + /> + + setOverlayState({ overlay: 'details', params: overlayState.params }) + } + onRename={() => + setOverlayState({ overlay: 'rename', params: overlayState.params }) + } + onDelete={(id) => { + handleDelete([id]); + handleCloseOverlay(); + }} + onClose={handleCloseOverlay} + /> + handleUpdate(id, 'name', value)} + onClose={handleCloseOverlay} + /> +
+
+ ); +} diff --git a/docs/data/material/components/autocomplete/ListViewAdvanced.tsx b/docs/data/material/components/autocomplete/ListViewAdvanced.tsx new file mode 100644 index 00000000000000..e7b9c692bededa --- /dev/null +++ b/docs/data/material/components/autocomplete/ListViewAdvanced.tsx @@ -0,0 +1,375 @@ +import * as React from 'react'; +import { + GridActionsCellItem, + GridColDef, + useGridApiRef, + GridRowParams, + DataGridPremium, + GridRowId, + gridClasses, + GridRowModel, +} from '@mui/x-data-grid-premium'; +import EditIcon from '@mui/icons-material/Edit'; +import DeleteIcon from '@mui/icons-material/Delete'; +import Avatar from '@mui/material/Avatar'; +import Stack from '@mui/material/Stack'; +import OpenIcon from '@mui/icons-material/Visibility'; +import useMediaQuery from '@mui/material/useMediaQuery'; +import CSSBaseline from '@mui/material/CssBaseline'; +import { randomId } from '@mui/x-data-grid-generator'; +import { FileIcon } from './components/FileIcon'; +import { DetailsDrawer } from './components/DetailsDrawer'; +import { ListCell } from './components/ListCell'; +import { Toolbar } from './components/Toolbar'; +import { INITIAL_ROWS } from './data'; +import { FILE_TYPES } from './constants'; +import { RowModel, FileType } from './types'; +import { formatDate, formatSize, stringAvatar } from './utils'; +import { ActionDrawer } from './components/ActionDrawer'; +import { RenameDialog } from './components/RenameDialog'; + +export default function ListViewAdvanced() { + // This is used only for the example - renders the drawer inside the container + const containerRef = React.useRef(null); + const container = () => containerRef.current as HTMLElement; + + const isListView = useMediaQuery('(min-width: 700px)'); + + const apiRef = useGridApiRef(); + + const [rows, setRows] = React.useState[]>(INITIAL_ROWS); + + const [loading, setLoading] = React.useState(false); + + const [overlayState, setOverlayState] = React.useState<{ + overlay: 'actions' | 'details' | 'rename' | null; + params: Pick, 'row'> | null; + }>({ + overlay: null, + params: null, + }); + + const handleCloseOverlay = () => { + setOverlayState({ overlay: null, params: null }); + }; + + const handleDelete = React.useCallback((ids: GridRowId[]) => { + setRows((prevRows) => prevRows.filter((row) => !ids.includes(row.id))); + }, []); + + const handleUpdate = React.useCallback( + ( + id: GridRowId, + field: GridRowParams['columns'][number]['field'], + value: string, + ) => { + setRows((prevRows) => + prevRows.map((row) => + row.id === id + ? { ...row, [field]: value, updatedAt: new Date().toISOString() } + : row, + ), + ); + }, + [], + ); + + const handleUpload = React.useCallback( + (event: React.ChangeEvent) => { + if (!event.target.files) { + return; + } + + const file = event.target.files[0]; + const createdAt = new Date().toISOString(); + + const fileType = file.type.split('/')[1]; + + // validate file type + if (!FILE_TYPES.includes(fileType as FileType)) { + alert('Invalid file type'); + return; + } + + const row: RowModel = { + id: randomId(), + name: file.name, + description: '', + type: fileType as FileType, + size: file.size, + createdBy: 'Kenan Yusuf', + createdAt, + updatedAt: createdAt, + state: 'pending', + }; + + event.target.value = ''; + + // Add temporary row + setLoading(true); + setRows((prevRows) => [...prevRows, row]); + + // Simulate server response time + const timeout = Math.floor(Math.random() * 3000) + 2000; + setTimeout(() => { + const uploadedRow: RowModel = { ...row, state: 'uploaded' }; + setRows((prevRows) => + prevRows.map((r) => (r.id === row.id ? uploadedRow : r)), + ); + setOverlayState({ overlay: 'actions', params: { row } }); + setLoading(false); + }, timeout); + }, + [], + ); + + const columns: GridColDef[] = React.useMemo( + () => [ + { + field: 'name', + headerName: 'Name', + width: 350, + editable: true, + hideable: false, + renderCell: (params) => { + return ( + + + {params.value} + + ); + }, + }, + { + field: 'createdBy', + headerName: 'Owner', + width: 200, + renderCell: (params) => { + const avatarProps = stringAvatar(params.value); + return ( + + + {params.value} + + ); + }, + }, + { + field: 'createdAt', + headerName: 'Added', + type: 'date', + width: 200, + valueFormatter: formatDate, + }, + { + field: 'updatedAt', + headerName: 'Modified', + type: 'date', + width: 200, + valueFormatter: formatDate, + }, + { + field: 'type', + headerName: 'Type', + width: 150, + }, + { + field: 'size', + headerName: 'Size', + width: 120, + valueFormatter: formatSize, + }, + { + type: 'actions', + field: 'actions', + resizable: false, + width: 50, + getActions: (params) => [ + } + onClick={() => { + setOverlayState({ overlay: 'actions', params }); + }} + showInMenu + />, + } + onClick={() => + apiRef.current?.startCellEditMode({ + id: params.id, + field: 'name', + }) + } + showInMenu + />, + } + onClick={() => handleDelete([params.id])} + showInMenu + />, + ], + }, + ], + [handleDelete, apiRef], + ); + + const listColDef: GridColDef = React.useMemo( + () => ({ + field: 'listCell', + renderCell: (params) => ( + { + setOverlayState({ overlay: 'actions', params }); + }} + /> + ), + }), + [], + ); + + const getEstimatedRowHeight = () => { + const density = apiRef.current?.state?.density; + + if (isListView) { + switch (density) { + case 'compact': + return 47; + case 'standard': + return 67; + case 'comfortable': + return 97; + default: + return 67; + } + } else { + switch (density) { + case 'compact': + return 47; + case 'standard': + return 55; + case 'comfortable': + return 63; + default: + return 55; + } + } + }; + + const getRowHeight = React.useCallback( + () => (isListView ? 'auto' : undefined), + [isListView], + ); + + return ( + + +
+ + setOverlayState({ overlay: 'actions', params }) + } + hideFooterSelectedRowCount + /> + + handleUpdate(id, 'description', value)} + onClose={handleCloseOverlay} + /> + + + setOverlayState({ overlay: 'details', params: overlayState.params }) + } + onRename={() => + setOverlayState({ overlay: 'rename', params: overlayState.params }) + } + onDelete={(id) => { + handleDelete([id]); + handleCloseOverlay(); + }} + onClose={handleCloseOverlay} + /> + + handleUpdate(id, 'name', value)} + onClose={handleCloseOverlay} + /> +
+
+ ); +} diff --git a/docs/data/material/components/autocomplete/autocomplete.md b/docs/data/material/components/autocomplete/autocomplete.md index 0f7b7c214ce503..eccc8b4b1999f9 100644 --- a/docs/data/material/components/autocomplete/autocomplete.md +++ b/docs/data/material/components/autocomplete/autocomplete.md @@ -354,6 +354,12 @@ Search within 10,000 randomly generated options. The list is virtualized thanks {{"demo": "Virtualize.js"}} +## Advanced usage + +The list view feature can be combined with [custom subcomponents](/x/react-data-grid/components/) to provide an improved user experience on small screens. + +{{"demo": "ListViewAdvanced.js", "bg": "inline", "maxWidth": 360, "height": 600}} + ## Events If you would like to prevent the default key handler behavior, you can set the event's `defaultMuiPrevented` property to `true`: diff --git a/docs/data/material/components/autocomplete/components/ActionDrawer.js b/docs/data/material/components/autocomplete/components/ActionDrawer.js new file mode 100644 index 00000000000000..8c4e29e9955d9f --- /dev/null +++ b/docs/data/material/components/autocomplete/components/ActionDrawer.js @@ -0,0 +1,88 @@ +import * as React from 'react'; + +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +import ListItemButton from '@mui/material/ListItemButton'; +import Stack from '@mui/material/Stack'; +import Typography from '@mui/material/Typography'; +import EditIcon from '@mui/icons-material/Edit'; +import DeleteIcon from '@mui/icons-material/Delete'; +import OpenIcon from '@mui/icons-material/Visibility'; +import { FileIcon } from './FileIcon'; +import { formatDate, formatSize } from '../utils'; +import { Drawer, DrawerHeader } from './Drawer'; + +function DrawerContent(props) { + const { params, onDelete, onPreview, onRename } = props; + return ( + + + + + {params.row.name} + + + {params.row.createdBy} + + + · + + + {formatSize(params.row.size)} + + + + {params.row.updatedAt + ? `Updated ${formatDate(params.row.updatedAt)}` + : `Added ${formatDate(params.row.createdAt)}`} + + + + + + + + + + + Preview + + + + + + + + Rename + + + + onDelete(params.row.id)}> + + + + Delete + + + + + ); +} + +export function ActionDrawer(props) { + const { params, onPreview, onRename, onDelete, ...other } = props; + return ( + + {params && ( + + )} + + ); +} diff --git a/docs/data/material/components/autocomplete/components/ActionDrawer.tsx b/docs/data/material/components/autocomplete/components/ActionDrawer.tsx new file mode 100644 index 00000000000000..533c8cddad5fb1 --- /dev/null +++ b/docs/data/material/components/autocomplete/components/ActionDrawer.tsx @@ -0,0 +1,101 @@ +import * as React from 'react'; +import { GridRowId, GridRowParams } from '@mui/x-data-grid-premium'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +import ListItemButton from '@mui/material/ListItemButton'; +import Stack from '@mui/material/Stack'; +import Typography from '@mui/material/Typography'; +import EditIcon from '@mui/icons-material/Edit'; +import DeleteIcon from '@mui/icons-material/Delete'; +import OpenIcon from '@mui/icons-material/Visibility'; +import { FileIcon } from './FileIcon'; +import { formatDate, formatSize } from '../utils'; +import { Drawer, DrawerHeader, DrawerProps } from './Drawer'; +import { RowModel } from '../types'; + +interface ActionDrawerProps extends DrawerProps { + params: Pick, 'row'> | null; + onPreview: () => void; + onRename: () => void; + onDelete: (id: GridRowId) => void; +} + +function DrawerContent( + props: { params: Pick, 'row'> } & Pick< + ActionDrawerProps, + 'onDelete' | 'onPreview' | 'onRename' + >, +) { + const { params, onDelete, onPreview, onRename } = props; + return ( + + + + + {params.row.name} + + + {params.row.createdBy} + + + · + + + {formatSize(params.row.size)} + + + + {params.row.updatedAt + ? `Updated ${formatDate(params.row.updatedAt)}` + : `Added ${formatDate(params.row.createdAt)}`} + + + + + + + + + + + Preview + + + + + + + + Rename + + + + onDelete(params.row.id)}> + + + + Delete + + + + + ); +} + +export function ActionDrawer(props: ActionDrawerProps) { + const { params, onPreview, onRename, onDelete, ...other } = props; + return ( + + {params && ( + + )} + + ); +} diff --git a/docs/data/material/components/autocomplete/components/Card.js b/docs/data/material/components/autocomplete/components/Card.js new file mode 100644 index 00000000000000..5d2e880bf605b3 --- /dev/null +++ b/docs/data/material/components/autocomplete/components/Card.js @@ -0,0 +1,70 @@ +import * as React from 'react'; +import Stack from '@mui/material/Stack'; +import Typography from '@mui/material/Typography'; + +export function Card(props) { + const { children, ...other } = props; + return ( + + {children} + + ); +} + +export function CardMedia(props) { + const { children, ...other } = props; + return ( + + {children} + + ); +} + +export function CardContent(props) { + const { children, ...other } = props; + return ( + + {children} + + ); +} + +export function CardTitle(props) { + const { children, ...other } = props; + return ( + + {children} + + ); +} + +export function CardDetailList(props) { + const { children, ...other } = props; + return ( + + {children} + + ); +} + +export function CardDetail(props) { + const { children, ...other } = props; + return ( + + {children} + + ); +} diff --git a/docs/data/material/components/autocomplete/components/Card.tsx b/docs/data/material/components/autocomplete/components/Card.tsx new file mode 100644 index 00000000000000..bd0df76f5db159 --- /dev/null +++ b/docs/data/material/components/autocomplete/components/Card.tsx @@ -0,0 +1,70 @@ +import * as React from 'react'; +import Stack, { StackProps } from '@mui/material/Stack'; +import Typography, { TypographyProps } from '@mui/material/Typography'; + +export function Card(props: StackProps) { + const { children, ...other } = props; + return ( + + {children} + + ); +} + +export function CardMedia(props: StackProps) { + const { children, ...other } = props; + return ( + + {children} + + ); +} + +export function CardContent(props: StackProps) { + const { children, ...other } = props; + return ( + + {children} + + ); +} + +export function CardTitle(props: TypographyProps) { + const { children, ...other } = props; + return ( + + {children} + + ); +} + +export function CardDetailList(props: StackProps) { + const { children, ...other } = props; + return ( + + {children} + + ); +} + +export function CardDetail(props: TypographyProps) { + const { children, ...other } = props; + return ( + + {children} + + ); +} diff --git a/docs/data/material/components/autocomplete/components/DetailsDrawer.js b/docs/data/material/components/autocomplete/components/DetailsDrawer.js new file mode 100644 index 00000000000000..44b1808c622b7c --- /dev/null +++ b/docs/data/material/components/autocomplete/components/DetailsDrawer.js @@ -0,0 +1,142 @@ +import * as React from 'react'; + +import Divider from '@mui/material/Divider'; +import Stack from '@mui/material/Stack'; +import Typography from '@mui/material/Typography'; +import TextField from '@mui/material/TextField'; +import Avatar from '@mui/material/Avatar'; +import Box from '@mui/material/Box'; +import Button from '@mui/material/Button'; +import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; +import { Drawer, DrawerHeader } from './Drawer'; +import { FileIcon } from './FileIcon'; +import { formatDate, formatSize, stringAvatar } from '../utils'; + +function Thumbnail() { + return ( + ({ + aspectRatio: '16/9', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + color: 'text.secondary', + borderRadius: 2, + gap: 1, + backgroundColor: 'grey.200', + ...theme.applyStyles('dark', { + backgroundColor: 'grey.800', + }), + })} + > + + + No preview available + + + ); +} + +function DrawerContent(props) { + const { params, onDescriptionChange, onClose } = props; + const [description, setDescription] = React.useState(params.row.description || ''); + const avatarProps = stringAvatar(params.row.createdBy); + + const handleSave = (event) => { + onDescriptionChange(params.row.id, description); + onClose(event); + }; + + return ( + + + + {params.row.name} + + + + + + setDescription(event.target.value)} + sx={{ mt: 1 }} + multiline + /> + + + + Type + + {params.row.type} + + + + + Size + + {formatSize(params.row.size)} + + + + + Created + + {formatDate(params.row.createdAt)} + + + + + Modified + + {formatDate(params.row.updatedAt)} + + + + + Owner + + + + + {params.row.createdBy} + + + + ); +} + +export function DetailsDrawer(props) { + const { params, listView, onDescriptionChange, onClose, ...other } = props; + return ( + + {params && ( + + )} + + ); +} diff --git a/docs/data/material/components/autocomplete/components/DetailsDrawer.tsx b/docs/data/material/components/autocomplete/components/DetailsDrawer.tsx new file mode 100644 index 00000000000000..6e4f2545dfeb1a --- /dev/null +++ b/docs/data/material/components/autocomplete/components/DetailsDrawer.tsx @@ -0,0 +1,158 @@ +import * as React from 'react'; +import { GridRowId, GridRowParams } from '@mui/x-data-grid-premium'; +import Divider from '@mui/material/Divider'; +import Stack from '@mui/material/Stack'; +import Typography from '@mui/material/Typography'; +import TextField from '@mui/material/TextField'; +import Avatar from '@mui/material/Avatar'; +import Box from '@mui/material/Box'; +import Button from '@mui/material/Button'; +import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; +import { Drawer, DrawerHeader, DrawerProps } from './Drawer'; +import { FileIcon } from './FileIcon'; +import { formatDate, formatSize, stringAvatar } from '../utils'; +import { RowModel } from '../types'; + +interface DetailsDrawerProps extends DrawerProps { + params: Pick, 'row'> | null; + listView: boolean; + onDescriptionChange: (id: GridRowId, value: string) => void; +} + +function Thumbnail() { + return ( + ({ + aspectRatio: '16/9', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + color: 'text.secondary', + borderRadius: 2, + gap: 1, + backgroundColor: 'grey.200', + ...theme.applyStyles('dark', { + backgroundColor: 'grey.800', + }), + })} + > + + + No preview available + + + ); +} + +function DrawerContent( + props: { params: Pick, 'row'> } & Pick< + DetailsDrawerProps, + 'onDescriptionChange' | 'onClose' + >, +) { + const { params, onDescriptionChange, onClose } = props; + const [description, setDescription] = React.useState(params.row.description || ''); + const avatarProps = stringAvatar(params.row.createdBy); + + const handleSave = (event: React.MouseEvent) => { + onDescriptionChange(params.row.id, description); + onClose(event); + }; + + return ( + + + + {params.row.name} + + + + + + + setDescription(event.target.value)} + sx={{ mt: 1 }} + multiline + /> + + + + + + Type + + {params.row.type} + + + + + Size + + {formatSize(params.row.size)} + + + + + Created + + {formatDate(params.row.createdAt)} + + + + + Modified + + {formatDate(params.row.updatedAt)} + + + + + + Owner + + + + + {params.row.createdBy} + + + + ); +} + +export function DetailsDrawer(props: DetailsDrawerProps) { + const { params, listView, onDescriptionChange, onClose, ...other } = props; + return ( + + {params && ( + + )} + + ); +} diff --git a/docs/data/material/components/autocomplete/components/Drawer.js b/docs/data/material/components/autocomplete/components/Drawer.js new file mode 100644 index 00000000000000..fcf9d182a6a30b --- /dev/null +++ b/docs/data/material/components/autocomplete/components/Drawer.js @@ -0,0 +1,88 @@ +import * as React from 'react'; +import MUISwipeableDrawer from '@mui/material/SwipeableDrawer'; +import Box from '@mui/material/Box'; +import Stack from '@mui/material/Stack'; +import Paper from '@mui/material/Paper'; +import { useMediaQuery } from '@mui/system'; + +function SwipeIndicator() { + return ( + + + + ); +} + +export function DrawerHeader(props) { + const { children, ...other } = props; + + return ( + + + {children} + + + ); +} + +export function Drawer(props) { + const { children, anchor, width = 320, container, ...other } = props; + const isBottomDrawer = anchor === 'bottom'; + const isTouch = useMediaQuery('(hover: none)'); + + return ( + {}} // required by SwipeableDrawer but not used in this demo + > + {isTouch && isBottomDrawer && } + {children} + + ); +} diff --git a/docs/data/material/components/autocomplete/components/Drawer.tsx b/docs/data/material/components/autocomplete/components/Drawer.tsx new file mode 100644 index 00000000000000..a859781e4417d2 --- /dev/null +++ b/docs/data/material/components/autocomplete/components/Drawer.tsx @@ -0,0 +1,97 @@ +import * as React from 'react'; +import MUISwipeableDrawer, { + SwipeableDrawerProps as MUISwipeableDrawerProps, +} from '@mui/material/SwipeableDrawer'; +import Box from '@mui/material/Box'; +import Stack, { StackProps } from '@mui/material/Stack'; +import Paper from '@mui/material/Paper'; +import { useMediaQuery } from '@mui/system'; + +function SwipeIndicator() { + return ( + + + + ); +} + +export interface DrawerHeaderProps extends StackProps {} + +export function DrawerHeader(props: DrawerHeaderProps) { + const { children, ...other } = props; + + return ( + + + {children} + + + ); +} + +export interface DrawerProps extends Omit { + width?: number; + container?: () => HTMLElement; +} + +export function Drawer(props: DrawerProps) { + const { children, anchor, width = 320, container, ...other } = props; + const isBottomDrawer = anchor === 'bottom'; + const isTouch = useMediaQuery('(hover: none)'); + + return ( + {}} // required by SwipeableDrawer but not used in this demo + > + {isTouch && isBottomDrawer && } + {children} + + ); +} diff --git a/docs/data/material/components/autocomplete/components/FileIcon.js b/docs/data/material/components/autocomplete/components/FileIcon.js new file mode 100644 index 00000000000000..bc1818bb50f4e5 --- /dev/null +++ b/docs/data/material/components/autocomplete/components/FileIcon.js @@ -0,0 +1,47 @@ +import * as React from 'react'; +import SvgIcon from '@mui/material/SvgIcon'; +import TextSnippetIcon from '@mui/icons-material/TextSnippet'; +import VideocamIcon from '@mui/icons-material/Videocam'; +import ImageIcon from '@mui/icons-material/Image'; +import FolderZipIcon from '@mui/icons-material/FolderZip'; + +const FILE_TYPE_ICONS = { + video: { + component: VideocamIcon, + color: 'error', + }, + image: { + component: ImageIcon, + color: 'error', + }, + document: { + component: TextSnippetIcon, + color: 'primary', + }, + archive: { + component: FolderZipIcon, + color: 'inherit', + }, +}; + +const FILE_ICON = { + pdf: FILE_TYPE_ICONS.document, + docx: FILE_TYPE_ICONS.document, + txt: FILE_TYPE_ICONS.document, + mp4: FILE_TYPE_ICONS.video, + mov: FILE_TYPE_ICONS.video, + webm: FILE_TYPE_ICONS.video, + jpg: FILE_TYPE_ICONS.image, + jpeg: FILE_TYPE_ICONS.image, + png: FILE_TYPE_ICONS.image, + gif: FILE_TYPE_ICONS.image, + tiff: FILE_TYPE_ICONS.image, + webp: FILE_TYPE_ICONS.image, + zip: FILE_TYPE_ICONS.archive, +}; + +export function FileIcon(props) { + const { type } = props; + const iconProps = FILE_ICON[type]; + return ; +} diff --git a/docs/data/material/components/autocomplete/components/FileIcon.tsx b/docs/data/material/components/autocomplete/components/FileIcon.tsx new file mode 100644 index 00000000000000..ac70cced33bf7a --- /dev/null +++ b/docs/data/material/components/autocomplete/components/FileIcon.tsx @@ -0,0 +1,54 @@ +import * as React from 'react'; +import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon'; +import TextSnippetIcon from '@mui/icons-material/TextSnippet'; +import VideocamIcon from '@mui/icons-material/Videocam'; +import ImageIcon from '@mui/icons-material/Image'; +import FolderZipIcon from '@mui/icons-material/FolderZip'; +import { FileType } from '../types'; + +const FILE_TYPE_ICONS = { + video: { + component: VideocamIcon, + color: 'error', + }, + image: { + component: ImageIcon, + color: 'error', + }, + document: { + component: TextSnippetIcon, + color: 'primary', + }, + archive: { + component: FolderZipIcon, + color: 'inherit', + }, +} satisfies Record< + string, + { component: React.ElementType; color: SvgIconProps['color'] } +>; + +const FILE_ICON: Record< + FileType, + { component: React.ElementType; color: SvgIconProps['color'] } +> = { + pdf: FILE_TYPE_ICONS.document, + docx: FILE_TYPE_ICONS.document, + txt: FILE_TYPE_ICONS.document, + mp4: FILE_TYPE_ICONS.video, + mov: FILE_TYPE_ICONS.video, + webm: FILE_TYPE_ICONS.video, + jpg: FILE_TYPE_ICONS.image, + jpeg: FILE_TYPE_ICONS.image, + png: FILE_TYPE_ICONS.image, + gif: FILE_TYPE_ICONS.image, + tiff: FILE_TYPE_ICONS.image, + webp: FILE_TYPE_ICONS.image, + zip: FILE_TYPE_ICONS.archive, +}; + +export function FileIcon(props: SvgIconProps & { type: FileType }) { + const { type } = props; + const iconProps = FILE_ICON[type]; + return ; +} diff --git a/docs/data/material/components/autocomplete/components/ListCell.js b/docs/data/material/components/autocomplete/components/ListCell.js new file mode 100644 index 00000000000000..19c1688b1d7485 --- /dev/null +++ b/docs/data/material/components/autocomplete/components/ListCell.js @@ -0,0 +1,110 @@ +import * as React from 'react'; +import { + gridColumnVisibilityModelSelector, + gridDensitySelector, + useGridApiContext, + useGridSelector, +} from '@mui/x-data-grid-premium'; +import IconButton from '@mui/material/IconButton'; +import Box from '@mui/material/Box'; +import GridMoreVertIcon from '@mui/icons-material/MoreVert'; +import { + Card, + CardContent, + CardDetailList, + CardDetail, + CardTitle, + CardMedia, +} from './Card'; +import { FileIcon } from './FileIcon'; +import { formatDate, formatSize } from '../utils'; + +const ICON_SIZE_BY_DENSITY = { + compact: 24, + standard: 32, + comfortable: 16, +}; + +function Thumbnail(props) { + const { fileIcon } = props; + return ( + ({ + position: 'relative', + borderRadius: 1, + width: 64, + height: 64, + overflow: 'hidden', + backgroundColor: 'grey.200', + ...theme.applyStyles('dark', { + backgroundColor: 'grey.800', + }), + })} + > + + {fileIcon} + + + ); +} + +export function ListCell(props) { + const { onOpenActions, ...params } = props; + const apiRef = useGridApiContext(); + const density = useGridSelector(apiRef, gridDensitySelector); + const columnVisibilityModel = useGridSelector( + apiRef, + gridColumnVisibilityModelSelector, + ); + + const showCreatedBy = columnVisibilityModel.createdBy !== false; + const showSize = columnVisibilityModel.size !== false; + const showCreatedAt = columnVisibilityModel.createdAt !== false; + const showUpdatedAt = columnVisibilityModel.updatedAt !== false; + const showThumbnail = density === 'comfortable'; + + const icon = ( + + ); + + return ( + + {showThumbnail ? : icon} + + {params.row.name} + {density !== 'compact' && (showCreatedBy || showSize) && ( + + {showCreatedBy && {params.row.createdBy}} + {showSize && {formatSize(params.row.size)}} + + )} + {density === 'comfortable' && (showCreatedAt || showUpdatedAt) && ( + + {showUpdatedAt && `Updated ${formatDate(params.row.updatedAt)}`} + + )} + + + { + event.stopPropagation(); + onOpenActions(); + }} + sx={{ mr: -0.75 }} + > + + + + ); +} diff --git a/docs/data/material/components/autocomplete/components/ListCell.tsx b/docs/data/material/components/autocomplete/components/ListCell.tsx new file mode 100644 index 00000000000000..250d5b82c2178a --- /dev/null +++ b/docs/data/material/components/autocomplete/components/ListCell.tsx @@ -0,0 +1,117 @@ +import * as React from 'react'; +import { + gridColumnVisibilityModelSelector, + GridDensity, + gridDensitySelector, + GridRenderCellParams, + useGridApiContext, + useGridSelector, +} from '@mui/x-data-grid-premium'; +import IconButton from '@mui/material/IconButton'; +import Box from '@mui/material/Box'; +import GridMoreVertIcon from '@mui/icons-material/MoreVert'; +import { + Card, + CardContent, + CardDetailList, + CardDetail, + CardTitle, + CardMedia, +} from './Card'; +import { FileIcon } from './FileIcon'; +import { formatDate, formatSize } from '../utils'; +import { RowModel } from '../types'; + +interface ListCellProps extends GridRenderCellParams { + onOpenActions: () => void; +} + +const ICON_SIZE_BY_DENSITY: Record = { + compact: 24, + standard: 32, + comfortable: 16, +}; + +function Thumbnail(props: { fileIcon: React.ReactNode }) { + const { fileIcon } = props; + return ( + ({ + position: 'relative', + borderRadius: 1, + width: 64, + height: 64, + overflow: 'hidden', + backgroundColor: 'grey.200', + ...theme.applyStyles('dark', { + backgroundColor: 'grey.800', + }), + })} + > + + {fileIcon} + + + ); +} + +export function ListCell(props: ListCellProps) { + const { onOpenActions, ...params } = props; + const apiRef = useGridApiContext(); + const density = useGridSelector(apiRef, gridDensitySelector); + const columnVisibilityModel = useGridSelector( + apiRef, + gridColumnVisibilityModelSelector, + ); + + const showCreatedBy = columnVisibilityModel.createdBy !== false; + const showSize = columnVisibilityModel.size !== false; + const showCreatedAt = columnVisibilityModel.createdAt !== false; + const showUpdatedAt = columnVisibilityModel.updatedAt !== false; + const showThumbnail = density === 'comfortable'; + + const icon = ( + + ); + + return ( + + {showThumbnail ? : icon} + + {params.row.name} + {density !== 'compact' && (showCreatedBy || showSize) && ( + + {showCreatedBy && {params.row.createdBy}} + {showSize && {formatSize(params.row.size)}} + + )} + {density === 'comfortable' && (showCreatedAt || showUpdatedAt) && ( + + {showUpdatedAt && `Updated ${formatDate(params.row.updatedAt)}`} + + )} + + + { + event.stopPropagation(); + onOpenActions(); + }} + sx={{ mr: -0.75 }} + > + + + + ); +} diff --git a/docs/data/material/components/autocomplete/components/RenameDialog.js b/docs/data/material/components/autocomplete/components/RenameDialog.js new file mode 100644 index 00000000000000..b7d1a49972c473 --- /dev/null +++ b/docs/data/material/components/autocomplete/components/RenameDialog.js @@ -0,0 +1,58 @@ +import * as React from 'react'; + +import Dialog from '@mui/material/Dialog'; +import DialogTitle from '@mui/material/DialogTitle'; +import DialogContent from '@mui/material/DialogContent'; +import DialogActions from '@mui/material/DialogActions'; +import Button from '@mui/material/Button'; +import TextField from '@mui/material/TextField'; + +export function RenameDialog(props) { + const { params, open, container, onSave, onClose } = props; + + const handleSave = (event) => { + event.preventDefault(); + + const formData = new FormData(event.currentTarget); + const value = formData.get('name'); + + onSave(params.row.id, value); + + onClose(); + }; + + return ( + + {params && ( + + Rename file + + + + + + + + + )} + + ); +} diff --git a/docs/data/material/components/autocomplete/components/RenameDialog.tsx b/docs/data/material/components/autocomplete/components/RenameDialog.tsx new file mode 100644 index 00000000000000..670e77c81ecd38 --- /dev/null +++ b/docs/data/material/components/autocomplete/components/RenameDialog.tsx @@ -0,0 +1,67 @@ +import * as React from 'react'; +import { GridRowId, GridRowParams } from '@mui/x-data-grid-premium'; +import Dialog from '@mui/material/Dialog'; +import DialogTitle from '@mui/material/DialogTitle'; +import DialogContent from '@mui/material/DialogContent'; +import DialogActions from '@mui/material/DialogActions'; +import Button from '@mui/material/Button'; +import TextField from '@mui/material/TextField'; +import { RowModel } from '../types'; + +export interface RenameDialogProps { + params: Pick, 'row'> | null; + open: boolean; + container?: () => HTMLElement; + onSave: (id: GridRowId, value: string) => void; + onClose: () => void; +} + +export function RenameDialog(props: RenameDialogProps) { + const { params, open, container, onSave, onClose } = props; + + const handleSave = (event: React.FormEvent) => { + event.preventDefault(); + + const formData = new FormData(event.currentTarget); + const value = formData.get('name') as string; + + onSave(params!.row.id, value); + + onClose(); + }; + + return ( + + {params && ( + + Rename file + + + + + + + + + )} + + ); +} diff --git a/docs/data/material/components/autocomplete/components/Toolbar.js b/docs/data/material/components/autocomplete/components/Toolbar.js new file mode 100644 index 00000000000000..412b5dc9f3c54f --- /dev/null +++ b/docs/data/material/components/autocomplete/components/Toolbar.js @@ -0,0 +1,105 @@ +import * as React from 'react'; +import { + GridClearIcon, + GridDeleteIcon, + GridToolbarContainer, + GridToolbarQuickFilter, + selectedGridRowsSelector, + useGridApiContext, + useGridSelector, +} from '@mui/x-data-grid-premium'; +import Box from '@mui/material/Box'; +import Typography from '@mui/material/Typography'; +import { outlinedInputClasses } from '@mui/material/OutlinedInput'; +import { iconButtonClasses } from '@mui/material/IconButton'; +import { ToolbarAddItem } from './ToolbarAddItem'; +import { ToolbarColumnsItem } from './ToolbarColumnsItem'; +import { ToolbarSortItem } from './ToolbarSortItem'; +import { ToolbarDensityItem } from './ToolbarDensityItem'; +import { ToolbarFilterItem } from './ToolbarFilterItem'; +import { ToolbarButton } from './ToolbarButton'; + +export function Toolbar(props) { + const { listView = false, container, handleUpload, handleDelete } = props; + const apiRef = useGridApiContext(); + const selectedRows = useGridSelector(apiRef, selectedGridRowsSelector); + const selectionCount = selectedRows.size; + const showSelectionOptions = selectionCount > 0; + + const handleClearSelection = () => { + apiRef.current.setRowSelectionModel([]); + }; + + const handleDeleteSelectedRows = () => { + handleClearSelection(); + handleDelete?.(Array.from(selectedRows.keys())); + }; + + const itemProps = { + listView, + container, + }; + + return ( + + {showSelectionOptions ? ( + + + + + + {selectionCount} selected + + + + + + ) : ( + + + + + + + + + + + + )} + + ); +} diff --git a/docs/data/material/components/autocomplete/components/Toolbar.tsx b/docs/data/material/components/autocomplete/components/Toolbar.tsx new file mode 100644 index 00000000000000..62980799d4b291 --- /dev/null +++ b/docs/data/material/components/autocomplete/components/Toolbar.tsx @@ -0,0 +1,115 @@ +import * as React from 'react'; +import { + GridClearIcon, + GridDeleteIcon, + GridRowId, + GridToolbarContainer, + GridToolbarProps, + GridToolbarQuickFilter, + selectedGridRowsSelector, + useGridApiContext, + useGridSelector, +} from '@mui/x-data-grid-premium'; +import Box from '@mui/material/Box'; +import Typography from '@mui/material/Typography'; +import { outlinedInputClasses } from '@mui/material/OutlinedInput'; +import { iconButtonClasses } from '@mui/material/IconButton'; +import { ToolbarAddItem } from './ToolbarAddItem'; +import { ToolbarColumnsItem } from './ToolbarColumnsItem'; +import { ToolbarSortItem } from './ToolbarSortItem'; +import { ToolbarDensityItem } from './ToolbarDensityItem'; +import { ToolbarFilterItem } from './ToolbarFilterItem'; +import { ToolbarButton } from './ToolbarButton'; +import { DrawerProps } from './Drawer'; + +export interface ToolbarProps extends GridToolbarProps { + container?: DrawerProps['container']; + listView?: boolean; + handleDelete?: (ids: GridRowId[]) => void; + handleUpload?: (event: React.ChangeEvent) => void; +} + +export function Toolbar(props: ToolbarProps) { + const { listView = false, container, handleUpload, handleDelete } = props; + const apiRef = useGridApiContext(); + const selectedRows = useGridSelector(apiRef, selectedGridRowsSelector); + const selectionCount = selectedRows.size; + const showSelectionOptions = selectionCount > 0; + + const handleClearSelection = () => { + apiRef.current.setRowSelectionModel([]); + }; + + const handleDeleteSelectedRows = () => { + handleClearSelection(); + handleDelete?.(Array.from(selectedRows.keys())); + }; + + const itemProps = { + listView, + container, + }; + + return ( + + {showSelectionOptions ? ( + + + + + + {selectionCount} selected + + + + + + ) : ( + + + + + + + + + + + + )} + + ); +} diff --git a/docs/data/material/components/autocomplete/components/ToolbarAddItem.js b/docs/data/material/components/autocomplete/components/ToolbarAddItem.js new file mode 100644 index 00000000000000..48053f1bb08fc1 --- /dev/null +++ b/docs/data/material/components/autocomplete/components/ToolbarAddItem.js @@ -0,0 +1,75 @@ +import * as React from 'react'; +import AddIcon from '@mui/icons-material/Add'; +import CloudUploadIcon from '@mui/icons-material/CloudUpload'; +import NewFolderIcon from '@mui/icons-material/CreateNewFolder'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +import ListItemButton from '@mui/material/ListItemButton'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import Typography from '@mui/material/Typography'; + +import { ToolbarButton } from './ToolbarButton'; +import { Drawer, DrawerHeader } from './Drawer'; + +const ListItemUploadButton = React.forwardRef( + function ListItemUploadButton(props, ref) { + const { children, ...other } = props; + return ( + + {children} + + ); + }, +); + +export function ToolbarAddItem(props) { + const { container } = props; + const [open, setOpen] = React.useState(false); + const { handleUpload, listView } = props; + + const handleFileSelect = (event) => { + handleUpload?.(event); + setOpen(false); + }; + + return ( + + setOpen(true)}> + + + + setOpen(false)} + > + + Add new + + + + + + + + + Upload file + + + + + + {}} disabled> + + + + New folder + + + + + + ); +} diff --git a/docs/data/material/components/autocomplete/components/ToolbarAddItem.tsx b/docs/data/material/components/autocomplete/components/ToolbarAddItem.tsx new file mode 100644 index 00000000000000..a3c43ffda857d5 --- /dev/null +++ b/docs/data/material/components/autocomplete/components/ToolbarAddItem.tsx @@ -0,0 +1,81 @@ +import * as React from 'react'; +import AddIcon from '@mui/icons-material/Add'; +import CloudUploadIcon from '@mui/icons-material/CloudUpload'; +import NewFolderIcon from '@mui/icons-material/CreateNewFolder'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +import ListItemButton from '@mui/material/ListItemButton'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import Typography from '@mui/material/Typography'; +import { ButtonProps } from '@mui/material/Button'; +import { ToolbarButton } from './ToolbarButton'; +import { Drawer, DrawerHeader, DrawerProps } from './Drawer'; + +const ListItemUploadButton = React.forwardRef( + function ListItemUploadButton(props, ref) { + const { children, ...other } = props; + return ( + + {children} + + ); + }, +); + +export interface ToolbarAddItemProps { + container: DrawerProps['container']; + listView: boolean; + handleUpload?: (event: React.ChangeEvent) => void; +} + +export function ToolbarAddItem(props: ToolbarAddItemProps) { + const { container } = props; + const [open, setOpen] = React.useState(false); + const { handleUpload, listView } = props; + + const handleFileSelect = (event: React.ChangeEvent) => { + handleUpload?.(event); + setOpen(false); + }; + + return ( + + setOpen(true)}> + + + + setOpen(false)} + > + + Add new + + + + + + + + + Upload file + + + + + + {}} disabled> + + + + New folder + + + + + + ); +} diff --git a/docs/data/material/components/autocomplete/components/ToolbarButton.js b/docs/data/material/components/autocomplete/components/ToolbarButton.js new file mode 100644 index 00000000000000..7ed7b6f21a51ae --- /dev/null +++ b/docs/data/material/components/autocomplete/components/ToolbarButton.js @@ -0,0 +1,7 @@ +import * as React from 'react'; +import IconButton from '@mui/material/IconButton'; + +export function ToolbarButton(props) { + const { className, children, ...other } = props; + return {children}; +} diff --git a/docs/data/material/components/autocomplete/components/ToolbarButton.tsx b/docs/data/material/components/autocomplete/components/ToolbarButton.tsx new file mode 100644 index 00000000000000..48b5dcf1ed3023 --- /dev/null +++ b/docs/data/material/components/autocomplete/components/ToolbarButton.tsx @@ -0,0 +1,8 @@ +import * as React from 'react'; +import IconButton from '@mui/material/IconButton'; +import { ButtonProps } from '@mui/material/Button'; + +export function ToolbarButton(props: ButtonProps) { + const { className, children, ...other } = props; + return {children}; +} diff --git a/docs/data/material/components/autocomplete/components/ToolbarColumnsItem.js b/docs/data/material/components/autocomplete/components/ToolbarColumnsItem.js new file mode 100644 index 00000000000000..e6fe57471fd599 --- /dev/null +++ b/docs/data/material/components/autocomplete/components/ToolbarColumnsItem.js @@ -0,0 +1,78 @@ +import * as React from 'react'; +import { + GridColumnIcon, + useGridApiContext, + useGridSelector, + gridColumnDefinitionsSelector, + gridColumnVisibilityModelSelector, +} from '@mui/x-data-grid-premium'; +import CheckBoxIcon from '@mui/icons-material/CheckBox'; +import CheckBoxBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank'; +import Typography from '@mui/material/Typography'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +import ListItemButton from '@mui/material/ListItemButton'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import { ToolbarButton } from './ToolbarButton'; +import { Drawer, DrawerHeader } from './Drawer'; + +export function ToolbarColumnsItem(props) { + const { listView, container } = props; + const [open, setOpen] = React.useState(false); + const apiRef = useGridApiContext(); + const columns = useGridSelector(apiRef, gridColumnDefinitionsSelector); + const columnVisibilityModel = useGridSelector( + apiRef, + gridColumnVisibilityModelSelector, + ); + + const toggleFieldVisibility = (field) => { + apiRef.current.setColumnVisibility( + field, + columnVisibilityModel[field] === false, + ); + }; + + return ( + + setOpen(true)}> + + + + setOpen(false)} + > + + Fields + + + + {columns.map((column) => { + const isVisible = columnVisibilityModel[column.field] !== false; + return ( + + toggleFieldVisibility(column.field)} + disabled={column.hideable === false} + > + + {isVisible ? ( + + ) : ( + + )} + + {column.headerName || column.field} + + + ); + })} + + + + ); +} diff --git a/docs/data/material/components/autocomplete/components/ToolbarColumnsItem.tsx b/docs/data/material/components/autocomplete/components/ToolbarColumnsItem.tsx new file mode 100644 index 00000000000000..f4f55499d06edb --- /dev/null +++ b/docs/data/material/components/autocomplete/components/ToolbarColumnsItem.tsx @@ -0,0 +1,83 @@ +import * as React from 'react'; +import { + GridColumnIcon, + useGridApiContext, + useGridSelector, + gridColumnDefinitionsSelector, + gridColumnVisibilityModelSelector, +} from '@mui/x-data-grid-premium'; +import CheckBoxIcon from '@mui/icons-material/CheckBox'; +import CheckBoxBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank'; +import Typography from '@mui/material/Typography'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +import ListItemButton from '@mui/material/ListItemButton'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import { ToolbarButton } from './ToolbarButton'; +import { Drawer, DrawerHeader, DrawerProps } from './Drawer'; + +interface ToolbarColumnsItemProps { + listView: boolean; + container: DrawerProps['container']; +} + +export function ToolbarColumnsItem(props: ToolbarColumnsItemProps) { + const { listView, container } = props; + const [open, setOpen] = React.useState(false); + const apiRef = useGridApiContext(); + const columns = useGridSelector(apiRef, gridColumnDefinitionsSelector); + const columnVisibilityModel = useGridSelector( + apiRef, + gridColumnVisibilityModelSelector, + ); + + const toggleFieldVisibility = (field: string) => { + apiRef.current.setColumnVisibility( + field, + columnVisibilityModel[field] === false, + ); + }; + + return ( + + setOpen(true)}> + + + + setOpen(false)} + > + + Fields + + + + {columns.map((column) => { + const isVisible = columnVisibilityModel[column.field] !== false; + return ( + + toggleFieldVisibility(column.field)} + disabled={column.hideable === false} + > + + {isVisible ? ( + + ) : ( + + )} + + {column.headerName || column.field} + + + ); + })} + + + + ); +} diff --git a/docs/data/material/components/autocomplete/components/ToolbarDensityItem.js b/docs/data/material/components/autocomplete/components/ToolbarDensityItem.js new file mode 100644 index 00000000000000..afb8447721ee05 --- /dev/null +++ b/docs/data/material/components/autocomplete/components/ToolbarDensityItem.js @@ -0,0 +1,87 @@ +import * as React from 'react'; +import { + GridViewStreamIcon, + useGridApiContext, + useGridSelector, + gridDensitySelector, + GridCheckIcon, + GridViewHeadlineIcon, + GridTableRowsIcon, +} from '@mui/x-data-grid-premium'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +import ListItemButton from '@mui/material/ListItemButton'; +import ListItemText from '@mui/material/ListItemText'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import Typography from '@mui/material/Typography'; +import { Drawer, DrawerHeader } from './Drawer'; +import { ToolbarButton } from './ToolbarButton'; + +const DENSITY_ICONS = { + compact: GridViewHeadlineIcon, + standard: GridTableRowsIcon, + comfortable: GridViewStreamIcon, +}; + +const DENSITY_OPTIONS = [ + { + label: 'Compact', + value: 'compact', + }, + { + label: 'Standard', + value: 'standard', + }, + { + label: 'Comfortable', + value: 'comfortable', + }, +]; + +export function ToolbarDensityItem(props) { + const { listView, container } = props; + const [open, setOpen] = React.useState(false); + const apiRef = useGridApiContext(); + const density = useGridSelector(apiRef, gridDensitySelector); + + const handleDensityChange = (value) => { + apiRef.current.setDensity(value); + setOpen(false); + }; + + const Icon = DENSITY_ICONS[density]; + + return ( + + setOpen(true)}> + + + + setOpen(false)} + > + + Density + + + + {DENSITY_OPTIONS.map((option) => { + const isActive = density === option.value; + + return ( + + handleDensityChange(option.value)}> + {isActive ? : null} + {option.label} + + + ); + })} + + + + ); +} diff --git a/docs/data/material/components/autocomplete/components/ToolbarDensityItem.tsx b/docs/data/material/components/autocomplete/components/ToolbarDensityItem.tsx new file mode 100644 index 00000000000000..8f9ce7a1846ed0 --- /dev/null +++ b/docs/data/material/components/autocomplete/components/ToolbarDensityItem.tsx @@ -0,0 +1,94 @@ +import * as React from 'react'; +import { + GridViewStreamIcon, + useGridApiContext, + useGridSelector, + GridDensityOption, + gridDensitySelector, + GridCheckIcon, + GridDensity, + GridViewHeadlineIcon, + GridTableRowsIcon, +} from '@mui/x-data-grid-premium'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +import ListItemButton from '@mui/material/ListItemButton'; +import ListItemText from '@mui/material/ListItemText'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import Typography from '@mui/material/Typography'; +import { Drawer, DrawerHeader, DrawerProps } from './Drawer'; +import { ToolbarButton } from './ToolbarButton'; + +const DENSITY_ICONS = { + compact: GridViewHeadlineIcon, + standard: GridTableRowsIcon, + comfortable: GridViewStreamIcon, +}; + +const DENSITY_OPTIONS: Omit[] = [ + { + label: 'Compact', + value: 'compact', + }, + { + label: 'Standard', + value: 'standard', + }, + { + label: 'Comfortable', + value: 'comfortable', + }, +]; + +interface ToolbarDensityItemProps { + listView: boolean; + container: DrawerProps['container']; +} + +export function ToolbarDensityItem(props: ToolbarDensityItemProps) { + const { listView, container } = props; + const [open, setOpen] = React.useState(false); + const apiRef = useGridApiContext(); + const density = useGridSelector(apiRef, gridDensitySelector); + + const handleDensityChange = (value: GridDensity) => { + apiRef.current.setDensity(value); + setOpen(false); + }; + + const Icon = DENSITY_ICONS[density]; + + return ( + + setOpen(true)}> + + + + setOpen(false)} + > + + Density + + + + {DENSITY_OPTIONS.map((option) => { + const isActive = density === option.value; + + return ( + + handleDensityChange(option.value)}> + {isActive ? : null} + {option.label} + + + ); + })} + + + + ); +} diff --git a/docs/data/material/components/autocomplete/components/ToolbarFilterItem.js b/docs/data/material/components/autocomplete/components/ToolbarFilterItem.js new file mode 100644 index 00000000000000..06cdb3c4690eff --- /dev/null +++ b/docs/data/material/components/autocomplete/components/ToolbarFilterItem.js @@ -0,0 +1,217 @@ +import * as React from 'react'; +import { + GridFilterListIcon, + useGridApiContext, + useGridSelector, + gridFilterActiveItemsSelector, + GridCheckIcon, +} from '@mui/x-data-grid-premium'; +import Badge from '@mui/material/Badge'; +import Typography from '@mui/material/Typography'; +import Divider from '@mui/material/Divider'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemButton from '@mui/material/ListItemButton'; +import ListItemText from '@mui/material/ListItemText'; +import ListSubheader from '@mui/material/ListSubheader'; +import CheckBoxIcon from '@mui/icons-material/CheckBox'; +import CheckBoxBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank'; +import FilterAltOffIcon from '@mui/icons-material/FilterAltOff'; +import { Drawer, DrawerHeader } from './Drawer'; +import { ToolbarButton } from './ToolbarButton'; + +import { FILE_TYPES } from '../constants'; + +const DATE_MODIFIED_FILTERS = [ + { + label: 'All', + id: 'all', + }, + { + label: 'Today', + id: 'today', + operator: 'onOrAfter', + value: new Date(new Date().setHours(0, 0, 0, 0)).toISOString(), + }, + { + label: 'Last week', + id: 'last-week', + operator: 'onOrAfter', + value: new Date( + new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).setHours(0, 0, 0, 0), + ).toISOString(), + }, + { + label: 'Last month', + id: 'last-month', + operator: 'onOrAfter', + value: new Date( + new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).setHours(0, 0, 0, 0), + ).toISOString(), + }, + { + label: 'Last 3 months', + id: 'last-3-months', + operator: 'onOrAfter', + value: new Date( + new Date(Date.now() - 3 * 30 * 24 * 60 * 60 * 1000).setHours(0, 0, 0, 0), + ).toISOString(), + }, +]; + +export function ToolbarFilterItem(props) { + const { listView, container } = props; + const [open, setOpen] = React.useState(false); + const apiRef = useGridApiContext(); + const activeFilters = useGridSelector(apiRef, gridFilterActiveItemsSelector); + const currentFileTypeFilter = + activeFilters.filter((filter) => filter.field === 'type')?.[0]?.value ?? []; + const currentDateModifiedFilter = activeFilters.find( + (filter) => filter.field === 'updatedAt', + ); + + const applyDateModifiedFilter = (filterItem) => { + if (currentDateModifiedFilter) { + apiRef.current.deleteFilterItem(currentDateModifiedFilter); + } + + apiRef.current.upsertFilterItem({ + field: 'updatedAt', + ...filterItem, + }); + }; + + const resetDateModifiedFilter = () => { + if (currentDateModifiedFilter) { + apiRef.current.deleteFilterItem(currentDateModifiedFilter); + } + }; + + const applyFileTypeFilter = (fileType, enable) => { + apiRef.current.upsertFilterItem({ + id: 'file-type', + field: 'type', + operator: 'isAnyOf', + value: enable + ? [...currentFileTypeFilter, fileType] + : currentFileTypeFilter.filter((type) => type !== fileType), + }); + }; + + const clearFilters = () => { + apiRef.current.setFilterModel({ + items: [], + }); + }; + + return ( + + setOpen(true)}> + + + + + + setOpen(false)} + > + + Filters + + + + Date modified + + } + > + {DATE_MODIFIED_FILTERS.map((option) => { + const isActive = + option.id === 'all' + ? !currentDateModifiedFilter + : activeFilters.some((filter) => filter.id === option.id); + + return ( + + + option.id === 'all' + ? resetDateModifiedFilter() + : applyDateModifiedFilter({ + id: option.id, + operator: option.operator, + value: option.value, + }) + } + > + {isActive ? : null} + {option.label} + + + ); + })} + + + + + File types + + } + > + {FILE_TYPES.map((type) => { + const isActive = currentFileTypeFilter.includes(type); + + return ( + + applyFileTypeFilter(type, !isActive)}> + + {isActive ? ( + + ) : ( + + )} + + {type} + + + ); + })} + + + + + + + + + + Clear filters + + + + + + ); +} diff --git a/docs/data/material/components/autocomplete/components/ToolbarFilterItem.tsx b/docs/data/material/components/autocomplete/components/ToolbarFilterItem.tsx new file mode 100644 index 00000000000000..2bb3040df9cd8d --- /dev/null +++ b/docs/data/material/components/autocomplete/components/ToolbarFilterItem.tsx @@ -0,0 +1,225 @@ +import * as React from 'react'; +import { + GridFilterListIcon, + useGridApiContext, + useGridSelector, + gridFilterActiveItemsSelector, + GridCheckIcon, + GridFilterItem, +} from '@mui/x-data-grid-premium'; +import Badge from '@mui/material/Badge'; +import Typography from '@mui/material/Typography'; +import Divider from '@mui/material/Divider'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemButton from '@mui/material/ListItemButton'; +import ListItemText from '@mui/material/ListItemText'; +import ListSubheader from '@mui/material/ListSubheader'; +import CheckBoxIcon from '@mui/icons-material/CheckBox'; +import CheckBoxBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank'; +import FilterAltOffIcon from '@mui/icons-material/FilterAltOff'; +import { Drawer, DrawerHeader, DrawerProps } from './Drawer'; +import { ToolbarButton } from './ToolbarButton'; +import { FileType } from '../types'; +import { FILE_TYPES } from '../constants'; + +const DATE_MODIFIED_FILTERS = [ + { + label: 'All', + id: 'all', + }, + { + label: 'Today', + id: 'today', + operator: 'onOrAfter', + value: new Date(new Date().setHours(0, 0, 0, 0)).toISOString(), + }, + { + label: 'Last week', + id: 'last-week', + operator: 'onOrAfter', + value: new Date( + new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).setHours(0, 0, 0, 0), + ).toISOString(), + }, + { + label: 'Last month', + id: 'last-month', + operator: 'onOrAfter', + value: new Date( + new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).setHours(0, 0, 0, 0), + ).toISOString(), + }, + { + label: 'Last 3 months', + id: 'last-3-months', + operator: 'onOrAfter', + value: new Date( + new Date(Date.now() - 3 * 30 * 24 * 60 * 60 * 1000).setHours(0, 0, 0, 0), + ).toISOString(), + }, +]; + +interface ToolbarFilterItemProps { + listView: boolean; + container: DrawerProps['container']; +} + +export function ToolbarFilterItem(props: ToolbarFilterItemProps) { + const { listView, container } = props; + const [open, setOpen] = React.useState(false); + const apiRef = useGridApiContext(); + const activeFilters = useGridSelector(apiRef, gridFilterActiveItemsSelector); + const currentFileTypeFilter = + activeFilters.filter((filter) => filter.field === 'type')?.[0]?.value ?? []; + const currentDateModifiedFilter = activeFilters.find( + (filter) => filter.field === 'updatedAt', + ); + + const applyDateModifiedFilter = (filterItem: Omit) => { + if (currentDateModifiedFilter) { + apiRef.current.deleteFilterItem(currentDateModifiedFilter); + } + + apiRef.current.upsertFilterItem({ + field: 'updatedAt', + ...filterItem, + }); + }; + + const resetDateModifiedFilter = () => { + if (currentDateModifiedFilter) { + apiRef.current.deleteFilterItem(currentDateModifiedFilter); + } + }; + + const applyFileTypeFilter = (fileType: FileType, enable: boolean) => { + apiRef.current.upsertFilterItem({ + id: 'file-type', + field: 'type', + operator: 'isAnyOf', + value: enable + ? [...currentFileTypeFilter, fileType] + : currentFileTypeFilter.filter((type: string) => type !== fileType), + }); + }; + + const clearFilters = () => { + apiRef.current.setFilterModel({ + items: [], + }); + }; + + return ( + + setOpen(true)}> + + + + + + setOpen(false)} + > + + Filters + + + + Date modified + + } + > + {DATE_MODIFIED_FILTERS.map((option) => { + const isActive = + option.id === 'all' + ? !currentDateModifiedFilter + : activeFilters.some((filter) => filter.id === option.id); + + return ( + + + option.id === 'all' + ? resetDateModifiedFilter() + : applyDateModifiedFilter({ + id: option.id, + operator: option.operator!, + value: option.value, + }) + } + > + {isActive ? : null} + {option.label} + + + ); + })} + + + + + + File types + + } + > + {FILE_TYPES.map((type) => { + const isActive = currentFileTypeFilter.includes(type); + + return ( + + applyFileTypeFilter(type, !isActive)}> + + {isActive ? ( + + ) : ( + + )} + + {type} + + + ); + })} + + + + + + + + + + + Clear filters + + + + + + ); +} diff --git a/docs/data/material/components/autocomplete/components/ToolbarSortItem.js b/docs/data/material/components/autocomplete/components/ToolbarSortItem.js new file mode 100644 index 00000000000000..91c07622847f20 --- /dev/null +++ b/docs/data/material/components/autocomplete/components/ToolbarSortItem.js @@ -0,0 +1,93 @@ +import * as React from 'react'; +import { + useGridApiContext, + GridArrowUpwardIcon, + GridArrowDownwardIcon, + useGridSelector, + gridSortModelSelector, + gridColumnDefinitionsSelector, +} from '@mui/x-data-grid-premium'; +import SwapVertIcon from '@mui/icons-material/SwapVert'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +import ListItemButton from '@mui/material/ListItemButton'; +import ListItemText from '@mui/material/ListItemText'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import Typography from '@mui/material/Typography'; +import Badge from '@mui/material/Badge'; +import { Drawer, DrawerHeader } from './Drawer'; +import { ToolbarButton } from './ToolbarButton'; + +export function ToolbarSortItem(props) { + const { listView, container } = props; + const [open, setOpen] = React.useState(false); + const apiRef = useGridApiContext(); + const fields = useGridSelector(apiRef, gridColumnDefinitionsSelector); + const sortModel = useGridSelector(apiRef, gridSortModelSelector); + const sortableFields = fields.filter((field) => field.sortable); + const sortCount = sortModel.length; + + const handleSortChange = (field, sort) => { + apiRef.current.sortColumn(field, sort, true); + }; + + return ( + + setOpen(true)}> + + + + + + setOpen(false)} + > + + Sort by + + + + {sortableFields.map((field) => { + const fieldIndexInSortModel = sortModel.findIndex( + (sort) => sort.field === field.field, + ); + const fieldInSortModel = sortModel[fieldIndexInSortModel]; + let nextSort = 'asc'; + + if (fieldInSortModel) { + nextSort = fieldInSortModel.sort === 'asc' ? 'desc' : null; + } + + return ( + + handleSortChange(field.field, nextSort)} + > + + {fieldInSortModel && ( + 1 ? fieldIndexInSortModel + 1 : null + } + > + {fieldInSortModel.sort === 'asc' ? ( + + ) : ( + + )} + + )} + + {field.headerName} + + + ); + })} + + + + ); +} diff --git a/docs/data/material/components/autocomplete/components/ToolbarSortItem.tsx b/docs/data/material/components/autocomplete/components/ToolbarSortItem.tsx new file mode 100644 index 00000000000000..4c3633f6ec3d64 --- /dev/null +++ b/docs/data/material/components/autocomplete/components/ToolbarSortItem.tsx @@ -0,0 +1,99 @@ +import * as React from 'react'; +import { + useGridApiContext, + GridArrowUpwardIcon, + GridArrowDownwardIcon, + useGridSelector, + gridSortModelSelector, + gridColumnDefinitionsSelector, + GridSortDirection, +} from '@mui/x-data-grid-premium'; +import SwapVertIcon from '@mui/icons-material/SwapVert'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +import ListItemButton from '@mui/material/ListItemButton'; +import ListItemText from '@mui/material/ListItemText'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import Typography from '@mui/material/Typography'; +import Badge from '@mui/material/Badge'; +import { Drawer, DrawerHeader, DrawerProps } from './Drawer'; +import { ToolbarButton } from './ToolbarButton'; + +interface ToolbarSortItemProps { + listView: boolean; + container: DrawerProps['container']; +} + +export function ToolbarSortItem(props: ToolbarSortItemProps) { + const { listView, container } = props; + const [open, setOpen] = React.useState(false); + const apiRef = useGridApiContext(); + const fields = useGridSelector(apiRef, gridColumnDefinitionsSelector); + const sortModel = useGridSelector(apiRef, gridSortModelSelector); + const sortableFields = fields.filter((field) => field.sortable); + const sortCount = sortModel.length; + + const handleSortChange = (field: string, sort: GridSortDirection) => { + apiRef.current.sortColumn(field, sort, true); + }; + + return ( + + setOpen(true)}> + + + + + + setOpen(false)} + > + + Sort by + + + + {sortableFields.map((field) => { + const fieldIndexInSortModel = sortModel.findIndex( + (sort) => sort.field === field.field, + ); + const fieldInSortModel = sortModel[fieldIndexInSortModel]; + let nextSort: GridSortDirection = 'asc'; + + if (fieldInSortModel) { + nextSort = fieldInSortModel.sort === 'asc' ? 'desc' : null; + } + + return ( + + handleSortChange(field.field, nextSort)} + > + + {fieldInSortModel && ( + 1 ? fieldIndexInSortModel + 1 : null + } + > + {fieldInSortModel.sort === 'asc' ? ( + + ) : ( + + )} + + )} + + {field.headerName} + + + ); + })} + + + + ); +} diff --git a/docs/data/material/components/autocomplete/constants.js b/docs/data/material/components/autocomplete/constants.js new file mode 100644 index 00000000000000..367df998d63747 --- /dev/null +++ b/docs/data/material/components/autocomplete/constants.js @@ -0,0 +1,15 @@ +export const FILE_TYPES = [ + 'pdf', + 'docx', + 'txt', + 'mp4', + 'mov', + 'webm', + 'jpg', + 'jpeg', + 'png', + 'gif', + 'tiff', + 'webp', + 'zip', +]; diff --git a/docs/data/material/components/autocomplete/constants.ts b/docs/data/material/components/autocomplete/constants.ts new file mode 100644 index 00000000000000..ee67fc4fb92c0f --- /dev/null +++ b/docs/data/material/components/autocomplete/constants.ts @@ -0,0 +1,17 @@ +import { FileType } from './types'; + +export const FILE_TYPES: FileType[] = [ + 'pdf', + 'docx', + 'txt', + 'mp4', + 'mov', + 'webm', + 'jpg', + 'jpeg', + 'png', + 'gif', + 'tiff', + 'webp', + 'zip', +]; diff --git a/docs/data/material/components/autocomplete/data.js b/docs/data/material/components/autocomplete/data.js new file mode 100644 index 00000000000000..39537f00c1f530 --- /dev/null +++ b/docs/data/material/components/autocomplete/data.js @@ -0,0 +1,202 @@ +import { randomId } from '@mui/x-data-grid-generator'; + +export const INITIAL_ROWS = [ + { + id: randomId(), + type: 'zip', + name: 'archive.zip', + description: 'Compressed archive of project files', + size: 128_313_213, + createdBy: 'Kenan Yusuf', + createdAt: new Date('2023-09-15T08:30:00').toISOString(), + updatedAt: new Date('2023-09-15T08:30:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'docx', + name: 'invoice-322.docx', + description: 'Invoice document for client 322', + size: 1_694_986, + createdBy: 'José Freitas', + createdAt: new Date('2024-01-18T11:30:00').toISOString(), + updatedAt: new Date().toISOString(), // Today + state: 'uploaded', + }, + { + id: randomId(), + type: 'png', + name: 'screenshot_2024-02-14_12-34-56.png', + description: 'Screenshot of application interface', + size: 522_078, + createdBy: 'José Freitas', + createdAt: new Date('2024-02-14T12:35:16').toISOString(), + updatedAt: new Date(Date.now() - 5 * 24 * 60 * 60 * 1000).toISOString(), // Last week + state: 'uploaded', + }, + { + id: randomId(), + type: 'mp4', + name: 'strategy-meeting.mp4', + description: 'Recording of the strategy planning meeting', + size: 2_442_044, + createdBy: 'José Freitas', + createdAt: new Date('2023-12-05T15:40:30').toISOString(), + updatedAt: new Date(Date.now() - 20 * 24 * 60 * 60 * 1000).toISOString(), // Last month + state: 'uploaded', + }, + { + id: randomId(), + type: 'docx', + name: 'project-proposal.docx', + description: 'Detailed project proposal document', + size: 3_567_890, + createdBy: 'Olivier Tassinari', + createdAt: new Date('2024-03-01T09:15:00').toISOString(), + updatedAt: new Date('2024-03-02T14:30:45').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'png', + name: 'logo-design-final.png', + description: 'Final version of the company logo design', + size: 1_234_567, + createdBy: 'Kenan Yusuf', + createdAt: new Date('2024-02-28T16:20:00').toISOString(), + updatedAt: new Date('2024-02-28T16:20:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'mp4', + name: 'product-demo.mp4', + description: 'Video demonstration of the new product features', + size: 15_789_012, + createdBy: 'Olivier Tassinari', + createdAt: new Date('2024-02-25T11:45:00').toISOString(), + updatedAt: new Date(Date.now() - 60 * 24 * 60 * 60 * 1000).toISOString(), // Last 3 months + state: 'uploaded', + }, + { + id: randomId(), + type: 'zip', + name: 'project-assets.zip', + description: 'Compressed folder containing all project assets', + size: 87_654_321, + createdBy: 'José Freitas', + createdAt: new Date('2024-03-03T13:00:00').toISOString(), + updatedAt: new Date('2024-03-03T13:00:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'docx', + name: 'meeting-minutes-2024-03-10.docx', + description: 'Minutes from the team meeting on March 10, 2024', + size: 567_890, + createdBy: 'Kenan Yusuf', + createdAt: new Date('2024-03-10T14:00:00').toISOString(), + updatedAt: new Date('2024-03-10T16:30:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'png', + name: 'ui-mockup-v2.png', + description: 'Updated user interface mockup', + size: 3_456_789, + createdBy: 'Olivier Tassinari', + createdAt: new Date('2024-03-05T10:20:00').toISOString(), + updatedAt: new Date('2024-03-05T10:20:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'mp4', + name: 'user-feedback-session.mp4', + description: 'Recording of user feedback session', + size: 234_567_890, + createdBy: 'José Freitas', + createdAt: new Date('2024-03-08T13:45:00').toISOString(), + updatedAt: new Date('2024-03-08T15:30:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'zip', + name: 'legacy-codebase.zip', + description: 'Archive of the legacy project codebase', + size: 567_890_123, + createdBy: 'Kenan Yusuf', + createdAt: new Date('2024-02-20T09:00:00').toISOString(), + updatedAt: new Date('2024-02-20T09:00:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'docx', + name: 'q1-2024-report.docx', + description: 'Quarterly report for Q1 2024', + size: 4_567_890, + createdBy: 'Olivier Tassinari', + createdAt: new Date('2024-03-31T23:59:59').toISOString(), + updatedAt: new Date('2024-04-01T10:15:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'png', + name: 'data-visualization.png', + description: 'Chart showing project progress', + size: 789_012, + createdBy: 'José Freitas', + createdAt: new Date('2024-03-15T11:30:00').toISOString(), + updatedAt: new Date('2024-03-15T11:30:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'mp4', + name: 'code-review-session.mp4', + description: 'Recording of code review meeting', + size: 345_678_901, + createdBy: 'Kenan Yusuf', + createdAt: new Date('2024-03-20T14:00:00').toISOString(), + updatedAt: new Date('2024-03-20T16:45:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'zip', + name: 'design-assets-v3.zip', + description: 'Compressed folder of updated design assets', + size: 98_765_432, + createdBy: 'Olivier Tassinari', + createdAt: new Date('2024-03-25T09:30:00').toISOString(), + updatedAt: new Date('2024-03-25T09:30:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'docx', + name: 'api-documentation.docx', + description: 'Comprehensive API documentation', + size: 2_345_678, + createdBy: 'José Freitas', + createdAt: new Date('2024-03-28T16:20:00').toISOString(), + updatedAt: new Date('2024-03-29T11:45:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'png', + name: 'error-screenshot.png', + description: 'Screenshot of error message for debugging', + size: 345_678, + createdBy: 'Kenan Yusuf', + createdAt: new Date('2024-03-30T08:15:00').toISOString(), + updatedAt: new Date('2024-03-30T08:15:00').toISOString(), + state: 'uploaded', + }, +]; diff --git a/docs/data/material/components/autocomplete/data.ts b/docs/data/material/components/autocomplete/data.ts new file mode 100644 index 00000000000000..3e54d301d2c7fd --- /dev/null +++ b/docs/data/material/components/autocomplete/data.ts @@ -0,0 +1,204 @@ +import { randomId } from '@mui/x-data-grid-generator'; +import { GridRowModel } from '@mui/x-data-grid-premium'; +import { RowModel } from './types'; + +export const INITIAL_ROWS: GridRowModel[] = [ + { + id: randomId(), + type: 'zip', + name: 'archive.zip', + description: 'Compressed archive of project files', + size: 128_313_213, + createdBy: 'Kenan Yusuf', + createdAt: new Date('2023-09-15T08:30:00').toISOString(), + updatedAt: new Date('2023-09-15T08:30:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'docx', + name: 'invoice-322.docx', + description: 'Invoice document for client 322', + size: 1_694_986, + createdBy: 'José Freitas', + createdAt: new Date('2024-01-18T11:30:00').toISOString(), + updatedAt: new Date().toISOString(), // Today + state: 'uploaded', + }, + { + id: randomId(), + type: 'png', + name: 'screenshot_2024-02-14_12-34-56.png', + description: 'Screenshot of application interface', + size: 522_078, + createdBy: 'José Freitas', + createdAt: new Date('2024-02-14T12:35:16').toISOString(), + updatedAt: new Date(Date.now() - 5 * 24 * 60 * 60 * 1000).toISOString(), // Last week + state: 'uploaded', + }, + { + id: randomId(), + type: 'mp4', + name: 'strategy-meeting.mp4', + description: 'Recording of the strategy planning meeting', + size: 2_442_044, + createdBy: 'José Freitas', + createdAt: new Date('2023-12-05T15:40:30').toISOString(), + updatedAt: new Date(Date.now() - 20 * 24 * 60 * 60 * 1000).toISOString(), // Last month + state: 'uploaded', + }, + { + id: randomId(), + type: 'docx', + name: 'project-proposal.docx', + description: 'Detailed project proposal document', + size: 3_567_890, + createdBy: 'Olivier Tassinari', + createdAt: new Date('2024-03-01T09:15:00').toISOString(), + updatedAt: new Date('2024-03-02T14:30:45').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'png', + name: 'logo-design-final.png', + description: 'Final version of the company logo design', + size: 1_234_567, + createdBy: 'Kenan Yusuf', + createdAt: new Date('2024-02-28T16:20:00').toISOString(), + updatedAt: new Date('2024-02-28T16:20:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'mp4', + name: 'product-demo.mp4', + description: 'Video demonstration of the new product features', + size: 15_789_012, + createdBy: 'Olivier Tassinari', + createdAt: new Date('2024-02-25T11:45:00').toISOString(), + updatedAt: new Date(Date.now() - 60 * 24 * 60 * 60 * 1000).toISOString(), // Last 3 months + state: 'uploaded', + }, + { + id: randomId(), + type: 'zip', + name: 'project-assets.zip', + description: 'Compressed folder containing all project assets', + size: 87_654_321, + createdBy: 'José Freitas', + createdAt: new Date('2024-03-03T13:00:00').toISOString(), + updatedAt: new Date('2024-03-03T13:00:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'docx', + name: 'meeting-minutes-2024-03-10.docx', + description: 'Minutes from the team meeting on March 10, 2024', + size: 567_890, + createdBy: 'Kenan Yusuf', + createdAt: new Date('2024-03-10T14:00:00').toISOString(), + updatedAt: new Date('2024-03-10T16:30:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'png', + name: 'ui-mockup-v2.png', + description: 'Updated user interface mockup', + size: 3_456_789, + createdBy: 'Olivier Tassinari', + createdAt: new Date('2024-03-05T10:20:00').toISOString(), + updatedAt: new Date('2024-03-05T10:20:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'mp4', + name: 'user-feedback-session.mp4', + description: 'Recording of user feedback session', + size: 234_567_890, + createdBy: 'José Freitas', + createdAt: new Date('2024-03-08T13:45:00').toISOString(), + updatedAt: new Date('2024-03-08T15:30:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'zip', + name: 'legacy-codebase.zip', + description: 'Archive of the legacy project codebase', + size: 567_890_123, + createdBy: 'Kenan Yusuf', + createdAt: new Date('2024-02-20T09:00:00').toISOString(), + updatedAt: new Date('2024-02-20T09:00:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'docx', + name: 'q1-2024-report.docx', + description: 'Quarterly report for Q1 2024', + size: 4_567_890, + createdBy: 'Olivier Tassinari', + createdAt: new Date('2024-03-31T23:59:59').toISOString(), + updatedAt: new Date('2024-04-01T10:15:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'png', + name: 'data-visualization.png', + description: 'Chart showing project progress', + size: 789_012, + createdBy: 'José Freitas', + createdAt: new Date('2024-03-15T11:30:00').toISOString(), + updatedAt: new Date('2024-03-15T11:30:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'mp4', + name: 'code-review-session.mp4', + description: 'Recording of code review meeting', + size: 345_678_901, + createdBy: 'Kenan Yusuf', + createdAt: new Date('2024-03-20T14:00:00').toISOString(), + updatedAt: new Date('2024-03-20T16:45:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'zip', + name: 'design-assets-v3.zip', + description: 'Compressed folder of updated design assets', + size: 98_765_432, + createdBy: 'Olivier Tassinari', + createdAt: new Date('2024-03-25T09:30:00').toISOString(), + updatedAt: new Date('2024-03-25T09:30:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'docx', + name: 'api-documentation.docx', + description: 'Comprehensive API documentation', + size: 2_345_678, + createdBy: 'José Freitas', + createdAt: new Date('2024-03-28T16:20:00').toISOString(), + updatedAt: new Date('2024-03-29T11:45:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'png', + name: 'error-screenshot.png', + description: 'Screenshot of error message for debugging', + size: 345_678, + createdBy: 'Kenan Yusuf', + createdAt: new Date('2024-03-30T08:15:00').toISOString(), + updatedAt: new Date('2024-03-30T08:15:00').toISOString(), + state: 'uploaded', + }, +]; diff --git a/docs/data/material/components/autocomplete/testFile.js b/docs/data/material/components/autocomplete/testFile.js deleted file mode 100644 index f1bb7a9b90f764..00000000000000 --- a/docs/data/material/components/autocomplete/testFile.js +++ /dev/null @@ -1,3 +0,0 @@ -const movies = [{ label: 'Monty Python and the Holy Grail', year: 1975 }]; - -export default movies; diff --git a/docs/data/material/components/autocomplete/top100Films.js b/docs/data/material/components/autocomplete/top100Films.js index 7202dbd0d32e5b..3226dcbc8ba7f3 100644 --- a/docs/data/material/components/autocomplete/top100Films.js +++ b/docs/data/material/components/autocomplete/top100Films.js @@ -1,5 +1,3 @@ -import movies from './testFile'; - // Top 100 films as rated by IMDb users. http://www.imdb.com/chart/top const top100Films = [ { label: 'The Shawshank Redemption', year: 1994 }, @@ -125,7 +123,7 @@ const top100Films = [ { label: 'Inglourious Basterds', year: 2009 }, { label: 'Snatch', year: 2000 }, { label: '3 Idiots', year: 2009 }, - ...movies, + { label: 'Monty Python and the Holy Grail', year: 1975 }, ]; export default top100Films; diff --git a/docs/data/material/components/autocomplete/types.ts b/docs/data/material/components/autocomplete/types.ts new file mode 100644 index 00000000000000..fd0975f3a0b952 --- /dev/null +++ b/docs/data/material/components/autocomplete/types.ts @@ -0,0 +1,30 @@ +import { GridRowId } from '@mui/x-data-grid-premium'; + +export type FileType = + | 'pdf' + | 'docx' + | 'txt' + | 'mp4' + | 'mov' + | 'webm' + | 'jpg' + | 'jpeg' + | 'png' + | 'gif' + | 'tiff' + | 'webp' + | 'zip'; + +export type FileState = 'uploaded' | 'pending'; + +export type RowModel = { + id: GridRowId; + type: FileType; + name: string; + description: string; + size: number; + createdBy: string; + createdAt: string; + updatedAt: string; + state: FileState; +}; diff --git a/docs/data/material/components/autocomplete/utils.js b/docs/data/material/components/autocomplete/utils.js new file mode 100644 index 00000000000000..8e75f8418c0ff4 --- /dev/null +++ b/docs/data/material/components/autocomplete/utils.js @@ -0,0 +1,56 @@ +export function formatDate(value) { + if (!value) { + return '—'; + } + const date = new Date(value); + const formatter = new Intl.DateTimeFormat('en-US', { + month: 'short', + day: '2-digit', + year: 'numeric', + hour: '2-digit', + minute: '2-digit', + }); + return formatter.format(date); +} + +export function formatSize(size) { + const units = ['B', 'KB', 'MB', 'GB', 'TB']; + let unitIndex = 0; + let formattedSize = size; + + while (formattedSize >= 1024 && unitIndex < units.length - 1) { + formattedSize /= 1024; + unitIndex += 1; + } + + return `${formattedSize.toFixed(2)} ${units[unitIndex]}`; +} + +export function stringToColor(string) { + let hash = 0; + let i; + + /* eslint-disable no-bitwise */ + for (i = 0; i < string.length; i += 1) { + hash = string.charCodeAt(i) + ((hash << 5) - hash); + } + + let color = '#'; + + for (i = 0; i < 3; i += 1) { + const value = (hash >> (i * 8)) & 0xff; + color += `00${value.toString(16)}`.slice(-2); + } + /* eslint-enable no-bitwise */ + + return color; +} + +export function stringAvatar(name) { + return { + sx: { + bgcolor: stringToColor(name), + }, + children: `${name.split(' ')[0][0]}${name.split(' ')[1][0]}`, + }; +} diff --git a/docs/data/material/components/autocomplete/utils.ts b/docs/data/material/components/autocomplete/utils.ts new file mode 100644 index 00000000000000..08c93be0d27c40 --- /dev/null +++ b/docs/data/material/components/autocomplete/utils.ts @@ -0,0 +1,56 @@ +export function formatDate(value: string | null) { + if (!value) { + return '—'; + } + const date = new Date(value); + const formatter = new Intl.DateTimeFormat('en-US', { + month: 'short', + day: '2-digit', + year: 'numeric', + hour: '2-digit', + minute: '2-digit', + }); + return formatter.format(date); +} + +export function formatSize(size: number) { + const units = ['B', 'KB', 'MB', 'GB', 'TB']; + let unitIndex = 0; + let formattedSize = size; + + while (formattedSize >= 1024 && unitIndex < units.length - 1) { + formattedSize /= 1024; + unitIndex += 1; + } + + return `${formattedSize.toFixed(2)} ${units[unitIndex]}`; +} + +export function stringToColor(string: string) { + let hash = 0; + let i: number; + + /* eslint-disable no-bitwise */ + for (i = 0; i < string.length; i += 1) { + hash = string.charCodeAt(i) + ((hash << 5) - hash); + } + + let color = '#'; + + for (i = 0; i < 3; i += 1) { + const value = (hash >> (i * 8)) & 0xff; + color += `00${value.toString(16)}`.slice(-2); + } + /* eslint-enable no-bitwise */ + + return color; +} + +export function stringAvatar(name: string) { + return { + sx: { + bgcolor: stringToColor(name), + }, + children: `${name.split(' ')[0][0]}${name.split(' ')[1][0]}`, + }; +} diff --git a/packages/markdown/loader.js b/packages/markdown/loader.js index c3d3eb97f551c7..4e1e6ba8922672 100644 --- a/packages/markdown/loader.js +++ b/packages/markdown/loader.js @@ -461,6 +461,7 @@ module.exports = async function demoLoader() { demos[demoName].relativeModules = {}; } + const addedModulesRelativeToModulePath = new Set(); await Promise.all( Array.from(relativeModules.get(demoName)).map(async ([relativeModuleID, variants]) => { let raw = ''; @@ -475,6 +476,7 @@ module.exports = async function demoLoader() { }); const importedProcessedModuleIDs = new Set(); + const importedProcessedModulesIDsParents = new Map(); // Find the relative paths in the relative module if (relativeModuleID.startsWith('.')) { extractImports(raw).forEach((importModuleID) => { @@ -487,32 +489,59 @@ module.exports = async function demoLoader() { ); if (importModuleID.startsWith('.')) { importedProcessedModuleIDs.add(importModuleID); + importedProcessedModulesIDsParents.set(importModuleID, relativeModuleFilePath); } }); - const moduleData = { module: relativeModuleID, raw }; - addToRelativeModules(moduleData, demoName, variants); + if (!addedModulesRelativeToModulePath.has(relativeModuleFilePath)) { + const moduleData = { module: relativeModuleID, raw }; + addToRelativeModules(moduleData, demoName, variants); + addedModulesRelativeToModulePath.add(relativeModuleFilePath); + } } // iterate recursively over the relative imports while (importedProcessedModuleIDs.size > 0) { for (const entry of importedProcessedModuleIDs) { if (entry.startsWith('.')) { - const entryModuleFilePath = path.join( - path.dirname(moduleFilepath), + const jsEntryModuleFilePath = path.join( + path.dirname(importedProcessedModulesIDsParents.get(entry)), entry + '.js', ); - const raw = await fs.readFile(entryModuleFilePath, { encoding: 'utf8' }); + const tsEntryModuleFilePath = path.join( + path.dirname(importedProcessedModulesIDsParents.get(entry)), + entry + '.ts', + ); + + let entryModuleFilePath = jsEntryModuleFilePath; + let raw = ''; + let module = entry + '.js'; + try { + raw = await fs.readFile(jsEntryModuleFilePath, { encoding: 'utf8' }); + } catch { + raw = await fs.readFile(tsEntryModuleFilePath, { encoding: 'utf8' }); + module = entry + '.ts'; + entryModuleFilePath = tsEntryModuleFilePath; + } extractImports(raw).forEach((importModuleID) => { // detect relative import detectRelativeImports(entry, entryModuleFilePath, 'JS', importModuleID); if (importModuleID.startsWith('.')) { importedProcessedModuleIDs.add(importModuleID); + importedProcessedModulesIDsParents.set(importModuleID, entryModuleFilePath); } }); - const moduleData = { module: entry + '.js', raw }; - addToRelativeModules(moduleData, demoName, variants); + + if (!addedModulesRelativeToModulePath.has(entryModuleFilePath)) { + const modulePathDirectory = moduleFilepath.split('/').slice(0, -1).join('/'); + const moduleData = { + module: '.' + entryModuleFilePath.replace(modulePathDirectory, ''), + raw, + }; + addToRelativeModules(moduleData, demoName, variants); + addedModulesRelativeToModulePath.add(entryModuleFilePath); + } } importedProcessedModuleIDs.delete(entry); } From 31b81e6a1ea2dd2a91091bef113b78a1caca84ec Mon Sep 17 00:00:00 2001 From: mnajdova Date: Mon, 21 Oct 2024 10:41:11 +0200 Subject: [PATCH 03/17] Update the script to support .js files --- .../components/autocomplete/ListView.js | 15 +++ .../autocomplete/components/ActionDrawer.js | 71 +++++++++++++- .../autocomplete/components/Card.js | 97 +++++++++++++++++-- .../autocomplete/components/DetailsDrawer.js | 80 ++++++++++++++- .../autocomplete/components/Drawer.js | 40 +++++++- .../autocomplete/components/FileIcon.js | 23 ++++- .../autocomplete/components/ListCell.js | 41 +++++++- .../autocomplete/components/RenameDialog.js | 39 +++++++- .../autocomplete/components/Toolbar.js | 12 ++- .../autocomplete/components/ToolbarAddItem.js | 18 +++- .../autocomplete/components/ToolbarButton.js | 13 ++- .../components/ToolbarColumnsItem.js | 10 +- .../components/ToolbarDensityItem.js | 10 +- .../components/ToolbarFilterItem.js | 10 +- .../components/ToolbarSortItem.js | 10 +- docs/scripts/formattedTSDemos.js | 3 +- 16 files changed, 471 insertions(+), 21 deletions(-) diff --git a/docs/data/material/components/autocomplete/ListView.js b/docs/data/material/components/autocomplete/ListView.js index a7ab930852afeb..8847a59f6a75eb 100644 --- a/docs/data/material/components/autocomplete/ListView.js +++ b/docs/data/material/components/autocomplete/ListView.js @@ -1,4 +1,5 @@ import * as React from 'react'; +import PropTypes from 'prop-types'; import { DataGridPro } from '@mui/x-data-grid-pro'; import Box from '@mui/material/Box'; import { useDemoData } from '@mui/x-data-grid-generator'; @@ -21,6 +22,13 @@ function MessageAction(params) { ); } +MessageAction.propTypes = { + /** + * The row model of the row that the current cell belongs to. + */ + row: PropTypes.any.isRequired, +}; + function ListViewCell(params) { return ( @@ -86,3 +120,38 @@ export function ActionDrawer(props) { ); } + +ActionDrawer.propTypes = { + onDelete: PropTypes.func.isRequired, + onPreview: PropTypes.func.isRequired, + onRename: PropTypes.func.isRequired, + params: PropTypes.shape({ + row: PropTypes.shape({ + createdAt: PropTypes.string.isRequired, + createdBy: PropTypes.string.isRequired, + description: PropTypes.string.isRequired, + id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + name: PropTypes.string.isRequired, + size: PropTypes.number.isRequired, + state: PropTypes.oneOf(['pending', 'uploaded']).isRequired, + type: PropTypes.oneOf([ + 'docx', + 'gif', + 'jpeg', + 'jpg', + 'mov', + 'mp4', + 'pdf', + 'png', + 'tiff', + 'txt', + 'webm', + 'webp', + 'zip', + ]).isRequired, + updatedAt: PropTypes.string.isRequired, + }).isRequired, + }), +}; + +export { ActionDrawer }; diff --git a/docs/data/material/components/autocomplete/components/Card.js b/docs/data/material/components/autocomplete/components/Card.js index 5d2e880bf605b3..a5f52ae73504b2 100644 --- a/docs/data/material/components/autocomplete/components/Card.js +++ b/docs/data/material/components/autocomplete/components/Card.js @@ -1,8 +1,9 @@ import * as React from 'react'; +import PropTypes from 'prop-types'; import Stack from '@mui/material/Stack'; import Typography from '@mui/material/Typography'; -export function Card(props) { +function Card(props) { const { children, ...other } = props; return ( @@ -42,7 +81,26 @@ export function CardContent(props) { ); } -export function CardTitle(props) { +CardContent.propTypes = { + /** + * The content of the component. + */ + children: PropTypes.node, + /** + * The system prop, which allows defining system overrides as well as additional CSS styles. + */ + sx: PropTypes.oneOfType([ + PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool]), + ), + PropTypes.func, + PropTypes.object, + ]), +}; + +export { CardContent }; + +function CardTitle(props) { const { children, ...other } = props; return ( @@ -51,7 +109,16 @@ export function CardTitle(props) { ); } -export function CardDetailList(props) { +CardTitle.propTypes = { + /** + * The content of the component. + */ + children: PropTypes.node, +}; + +export { CardTitle }; + +function CardDetailList(props) { const { children, ...other } = props; return ( @@ -60,7 +127,16 @@ export function CardDetailList(props) { ); } -export function CardDetail(props) { +CardDetailList.propTypes = { + /** + * The content of the component. + */ + children: PropTypes.node, +}; + +export { CardDetailList }; + +function CardDetail(props) { const { children, ...other } = props; return ( @@ -68,3 +144,12 @@ export function CardDetail(props) { ); } + +CardDetail.propTypes = { + /** + * The content of the component. + */ + children: PropTypes.node, +}; + +export { CardDetail }; diff --git a/docs/data/material/components/autocomplete/components/DetailsDrawer.js b/docs/data/material/components/autocomplete/components/DetailsDrawer.js index 44b1808c622b7c..2a990bf2c2e3b2 100644 --- a/docs/data/material/components/autocomplete/components/DetailsDrawer.js +++ b/docs/data/material/components/autocomplete/components/DetailsDrawer.js @@ -1,4 +1,5 @@ import * as React from 'react'; +import PropTypes from 'prop-types'; import Divider from '@mui/material/Divider'; import Stack from '@mui/material/Stack'; @@ -121,7 +122,44 @@ function DrawerContent(props) { ); } -export function DetailsDrawer(props) { +DrawerContent.propTypes = { + /** + * Callback fired when the component requests to be closed. + * + * @param {React.SyntheticEvent<{}>} event The event source of the callback. + */ + onClose: PropTypes.func.isRequired, + onDescriptionChange: PropTypes.func.isRequired, + params: PropTypes.shape({ + row: PropTypes.shape({ + createdAt: PropTypes.string.isRequired, + createdBy: PropTypes.string.isRequired, + description: PropTypes.string.isRequired, + id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + name: PropTypes.string.isRequired, + size: PropTypes.number.isRequired, + state: PropTypes.oneOf(['pending', 'uploaded']).isRequired, + type: PropTypes.oneOf([ + 'docx', + 'gif', + 'jpeg', + 'jpg', + 'mov', + 'mp4', + 'pdf', + 'png', + 'tiff', + 'txt', + 'webm', + 'webp', + 'zip', + ]).isRequired, + updatedAt: PropTypes.string.isRequired, + }).isRequired, + }).isRequired, +}; + +function DetailsDrawer(props) { const { params, listView, onDescriptionChange, onClose, ...other } = props; return ( ); } + +DetailsDrawer.propTypes = { + listView: PropTypes.bool.isRequired, + /** + * Callback fired when the component requests to be closed. + * + * @param {React.SyntheticEvent<{}>} event The event source of the callback. + */ + onClose: PropTypes.func.isRequired, + onDescriptionChange: PropTypes.func.isRequired, + params: PropTypes.shape({ + row: PropTypes.shape({ + createdAt: PropTypes.string.isRequired, + createdBy: PropTypes.string.isRequired, + description: PropTypes.string.isRequired, + id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + name: PropTypes.string.isRequired, + size: PropTypes.number.isRequired, + state: PropTypes.oneOf(['pending', 'uploaded']).isRequired, + type: PropTypes.oneOf([ + 'docx', + 'gif', + 'jpeg', + 'jpg', + 'mov', + 'mp4', + 'pdf', + 'png', + 'tiff', + 'txt', + 'webm', + 'webp', + 'zip', + ]).isRequired, + updatedAt: PropTypes.string.isRequired, + }).isRequired, + }), +}; + +export { DetailsDrawer }; diff --git a/docs/data/material/components/autocomplete/components/Drawer.js b/docs/data/material/components/autocomplete/components/Drawer.js index fcf9d182a6a30b..ec9c3ffa3a8d88 100644 --- a/docs/data/material/components/autocomplete/components/Drawer.js +++ b/docs/data/material/components/autocomplete/components/Drawer.js @@ -1,4 +1,5 @@ import * as React from 'react'; +import PropTypes from 'prop-types'; import MUISwipeableDrawer from '@mui/material/SwipeableDrawer'; import Box from '@mui/material/Box'; import Stack from '@mui/material/Stack'; @@ -28,7 +29,7 @@ function SwipeIndicator() { ); } -export function DrawerHeader(props) { +function DrawerHeader(props) { const { children, ...other } = props; return ( @@ -60,7 +61,16 @@ export function DrawerHeader(props) { ); } -export function Drawer(props) { +DrawerHeader.propTypes = { + /** + * The content of the component. + */ + children: PropTypes.node, +}; + +export { DrawerHeader }; + +function Drawer(props) { const { children, anchor, width = 320, container, ...other } = props; const isBottomDrawer = anchor === 'bottom'; const isTouch = useMediaQuery('(hover: none)'); @@ -86,3 +96,29 @@ export function Drawer(props) { ); } + +Drawer.propTypes = { + /** + * Side from which the drawer will appear. + * @default 'left' + */ + anchor: PropTypes.oneOf(['bottom', 'left', 'right', 'top']), + /** + * The content of the component. + */ + children: PropTypes.node, + /** + * An HTML element or function that returns one. + * The `container` will have the portal children appended to it. + * + * You can also provide a callback, which is called in a React layout effect. + * This lets you set the container from a ref, and also makes server-side rendering possible. + * + * By default, it uses the body of the top-level document object, + * so it's simply `document.body` most of the time. + */ + container: PropTypes.func, + width: PropTypes.number, +}; + +export { Drawer }; diff --git a/docs/data/material/components/autocomplete/components/FileIcon.js b/docs/data/material/components/autocomplete/components/FileIcon.js index bc1818bb50f4e5..24d70c875a3ffa 100644 --- a/docs/data/material/components/autocomplete/components/FileIcon.js +++ b/docs/data/material/components/autocomplete/components/FileIcon.js @@ -1,4 +1,5 @@ import * as React from 'react'; +import PropTypes from 'prop-types'; import SvgIcon from '@mui/material/SvgIcon'; import TextSnippetIcon from '@mui/icons-material/TextSnippet'; import VideocamIcon from '@mui/icons-material/Videocam'; @@ -40,8 +41,28 @@ const FILE_ICON = { zip: FILE_TYPE_ICONS.archive, }; -export function FileIcon(props) { +function FileIcon(props) { const { type } = props; const iconProps = FILE_ICON[type]; return ; } + +FileIcon.propTypes = { + type: PropTypes.oneOf([ + 'docx', + 'gif', + 'jpeg', + 'jpg', + 'mov', + 'mp4', + 'pdf', + 'png', + 'tiff', + 'txt', + 'webm', + 'webp', + 'zip', + ]).isRequired, +}; + +export { FileIcon }; diff --git a/docs/data/material/components/autocomplete/components/ListCell.js b/docs/data/material/components/autocomplete/components/ListCell.js index 19c1688b1d7485..0e2d0407ef98e3 100644 --- a/docs/data/material/components/autocomplete/components/ListCell.js +++ b/docs/data/material/components/autocomplete/components/ListCell.js @@ -1,4 +1,5 @@ import * as React from 'react'; +import PropTypes from 'prop-types'; import { gridColumnVisibilityModelSelector, gridDensitySelector, @@ -55,7 +56,11 @@ function Thumbnail(props) { ); } -export function ListCell(props) { +Thumbnail.propTypes = { + fileIcon: PropTypes.node, +}; + +function ListCell(props) { const { onOpenActions, ...params } = props; const apiRef = useGridApiContext(); const density = useGridSelector(apiRef, gridDensitySelector); @@ -108,3 +113,37 @@ export function ListCell(props) { ); } + +ListCell.propTypes = { + onOpenActions: PropTypes.func.isRequired, + /** + * The row model of the row that the current cell belongs to. + */ + row: PropTypes.shape({ + createdAt: PropTypes.string.isRequired, + createdBy: PropTypes.string.isRequired, + description: PropTypes.string.isRequired, + id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + name: PropTypes.string.isRequired, + size: PropTypes.number.isRequired, + state: PropTypes.oneOf(['pending', 'uploaded']).isRequired, + type: PropTypes.oneOf([ + 'docx', + 'gif', + 'jpeg', + 'jpg', + 'mov', + 'mp4', + 'pdf', + 'png', + 'tiff', + 'txt', + 'webm', + 'webp', + 'zip', + ]).isRequired, + updatedAt: PropTypes.string.isRequired, + }).isRequired, +}; + +export { ListCell }; diff --git a/docs/data/material/components/autocomplete/components/RenameDialog.js b/docs/data/material/components/autocomplete/components/RenameDialog.js index b7d1a49972c473..17815877da6b89 100644 --- a/docs/data/material/components/autocomplete/components/RenameDialog.js +++ b/docs/data/material/components/autocomplete/components/RenameDialog.js @@ -1,4 +1,5 @@ import * as React from 'react'; +import PropTypes from 'prop-types'; import Dialog from '@mui/material/Dialog'; import DialogTitle from '@mui/material/DialogTitle'; @@ -7,7 +8,7 @@ import DialogActions from '@mui/material/DialogActions'; import Button from '@mui/material/Button'; import TextField from '@mui/material/TextField'; -export function RenameDialog(props) { +function RenameDialog(props) { const { params, open, container, onSave, onClose } = props; const handleSave = (event) => { @@ -56,3 +57,39 @@ export function RenameDialog(props) { ); } + +RenameDialog.propTypes = { + container: PropTypes.func, + onClose: PropTypes.func.isRequired, + onSave: PropTypes.func.isRequired, + open: PropTypes.bool.isRequired, + params: PropTypes.shape({ + row: PropTypes.shape({ + createdAt: PropTypes.string.isRequired, + createdBy: PropTypes.string.isRequired, + description: PropTypes.string.isRequired, + id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + name: PropTypes.string.isRequired, + size: PropTypes.number.isRequired, + state: PropTypes.oneOf(['pending', 'uploaded']).isRequired, + type: PropTypes.oneOf([ + 'docx', + 'gif', + 'jpeg', + 'jpg', + 'mov', + 'mp4', + 'pdf', + 'png', + 'tiff', + 'txt', + 'webm', + 'webp', + 'zip', + ]).isRequired, + updatedAt: PropTypes.string.isRequired, + }).isRequired, + }), +}; + +export { RenameDialog }; diff --git a/docs/data/material/components/autocomplete/components/Toolbar.js b/docs/data/material/components/autocomplete/components/Toolbar.js index 412b5dc9f3c54f..2034a17a823632 100644 --- a/docs/data/material/components/autocomplete/components/Toolbar.js +++ b/docs/data/material/components/autocomplete/components/Toolbar.js @@ -1,4 +1,5 @@ import * as React from 'react'; +import PropTypes from 'prop-types'; import { GridClearIcon, GridDeleteIcon, @@ -19,7 +20,7 @@ import { ToolbarDensityItem } from './ToolbarDensityItem'; import { ToolbarFilterItem } from './ToolbarFilterItem'; import { ToolbarButton } from './ToolbarButton'; -export function Toolbar(props) { +function Toolbar(props) { const { listView = false, container, handleUpload, handleDelete } = props; const apiRef = useGridApiContext(); const selectedRows = useGridSelector(apiRef, selectedGridRowsSelector); @@ -103,3 +104,12 @@ export function Toolbar(props) { ); } + +Toolbar.propTypes = { + container: PropTypes.func, + handleDelete: PropTypes.func, + handleUpload: PropTypes.func, + listView: PropTypes.bool, +}; + +export { Toolbar }; diff --git a/docs/data/material/components/autocomplete/components/ToolbarAddItem.js b/docs/data/material/components/autocomplete/components/ToolbarAddItem.js index 48053f1bb08fc1..b903b8df60af4c 100644 --- a/docs/data/material/components/autocomplete/components/ToolbarAddItem.js +++ b/docs/data/material/components/autocomplete/components/ToolbarAddItem.js @@ -1,4 +1,5 @@ import * as React from 'react'; +import PropTypes from 'prop-types'; import AddIcon from '@mui/icons-material/Add'; import CloudUploadIcon from '@mui/icons-material/CloudUpload'; import NewFolderIcon from '@mui/icons-material/CreateNewFolder'; @@ -23,7 +24,14 @@ const ListItemUploadButton = React.forwardRef( }, ); -export function ToolbarAddItem(props) { +ListItemUploadButton.propTypes = { + /** + * The content of the component. + */ + children: PropTypes.node, +}; + +function ToolbarAddItem(props) { const { container } = props; const [open, setOpen] = React.useState(false); const { handleUpload, listView } = props; @@ -73,3 +81,11 @@ export function ToolbarAddItem(props) { ); } + +ToolbarAddItem.propTypes = { + container: PropTypes.func, + handleUpload: PropTypes.func, + listView: PropTypes.bool.isRequired, +}; + +export { ToolbarAddItem }; diff --git a/docs/data/material/components/autocomplete/components/ToolbarButton.js b/docs/data/material/components/autocomplete/components/ToolbarButton.js index 7ed7b6f21a51ae..78113d989a16eb 100644 --- a/docs/data/material/components/autocomplete/components/ToolbarButton.js +++ b/docs/data/material/components/autocomplete/components/ToolbarButton.js @@ -1,7 +1,18 @@ import * as React from 'react'; +import PropTypes from 'prop-types'; import IconButton from '@mui/material/IconButton'; -export function ToolbarButton(props) { +function ToolbarButton(props) { const { className, children, ...other } = props; return {children}; } + +ToolbarButton.propTypes = { + /** + * The content of the component. + */ + children: PropTypes.node, + className: PropTypes.string, +}; + +export { ToolbarButton }; diff --git a/docs/data/material/components/autocomplete/components/ToolbarColumnsItem.js b/docs/data/material/components/autocomplete/components/ToolbarColumnsItem.js index e6fe57471fd599..fd2034d8b269f3 100644 --- a/docs/data/material/components/autocomplete/components/ToolbarColumnsItem.js +++ b/docs/data/material/components/autocomplete/components/ToolbarColumnsItem.js @@ -1,4 +1,5 @@ import * as React from 'react'; +import PropTypes from 'prop-types'; import { GridColumnIcon, useGridApiContext, @@ -17,7 +18,7 @@ import ListItemText from '@mui/material/ListItemText'; import { ToolbarButton } from './ToolbarButton'; import { Drawer, DrawerHeader } from './Drawer'; -export function ToolbarColumnsItem(props) { +function ToolbarColumnsItem(props) { const { listView, container } = props; const [open, setOpen] = React.useState(false); const apiRef = useGridApiContext(); @@ -76,3 +77,10 @@ export function ToolbarColumnsItem(props) { ); } + +ToolbarColumnsItem.propTypes = { + container: PropTypes.func, + listView: PropTypes.bool.isRequired, +}; + +export { ToolbarColumnsItem }; diff --git a/docs/data/material/components/autocomplete/components/ToolbarDensityItem.js b/docs/data/material/components/autocomplete/components/ToolbarDensityItem.js index afb8447721ee05..132acf81a76317 100644 --- a/docs/data/material/components/autocomplete/components/ToolbarDensityItem.js +++ b/docs/data/material/components/autocomplete/components/ToolbarDensityItem.js @@ -1,4 +1,5 @@ import * as React from 'react'; +import PropTypes from 'prop-types'; import { GridViewStreamIcon, useGridApiContext, @@ -38,7 +39,7 @@ const DENSITY_OPTIONS = [ }, ]; -export function ToolbarDensityItem(props) { +function ToolbarDensityItem(props) { const { listView, container } = props; const [open, setOpen] = React.useState(false); const apiRef = useGridApiContext(); @@ -85,3 +86,10 @@ export function ToolbarDensityItem(props) { ); } + +ToolbarDensityItem.propTypes = { + container: PropTypes.func, + listView: PropTypes.bool.isRequired, +}; + +export { ToolbarDensityItem }; diff --git a/docs/data/material/components/autocomplete/components/ToolbarFilterItem.js b/docs/data/material/components/autocomplete/components/ToolbarFilterItem.js index 06cdb3c4690eff..990eee997a6cc7 100644 --- a/docs/data/material/components/autocomplete/components/ToolbarFilterItem.js +++ b/docs/data/material/components/autocomplete/components/ToolbarFilterItem.js @@ -1,4 +1,5 @@ import * as React from 'react'; +import PropTypes from 'prop-types'; import { GridFilterListIcon, useGridApiContext, @@ -60,7 +61,7 @@ const DATE_MODIFIED_FILTERS = [ }, ]; -export function ToolbarFilterItem(props) { +function ToolbarFilterItem(props) { const { listView, container } = props; const [open, setOpen] = React.useState(false); const apiRef = useGridApiContext(); @@ -215,3 +216,10 @@ export function ToolbarFilterItem(props) { ); } + +ToolbarFilterItem.propTypes = { + container: PropTypes.func, + listView: PropTypes.bool.isRequired, +}; + +export { ToolbarFilterItem }; diff --git a/docs/data/material/components/autocomplete/components/ToolbarSortItem.js b/docs/data/material/components/autocomplete/components/ToolbarSortItem.js index 91c07622847f20..c34894a3aaf49c 100644 --- a/docs/data/material/components/autocomplete/components/ToolbarSortItem.js +++ b/docs/data/material/components/autocomplete/components/ToolbarSortItem.js @@ -1,4 +1,5 @@ import * as React from 'react'; +import PropTypes from 'prop-types'; import { useGridApiContext, GridArrowUpwardIcon, @@ -18,7 +19,7 @@ import Badge from '@mui/material/Badge'; import { Drawer, DrawerHeader } from './Drawer'; import { ToolbarButton } from './ToolbarButton'; -export function ToolbarSortItem(props) { +function ToolbarSortItem(props) { const { listView, container } = props; const [open, setOpen] = React.useState(false); const apiRef = useGridApiContext(); @@ -91,3 +92,10 @@ export function ToolbarSortItem(props) { ); } + +ToolbarSortItem.propTypes = { + container: PropTypes.func, + listView: PropTypes.bool.isRequired, +}; + +export { ToolbarSortItem }; diff --git a/docs/scripts/formattedTSDemos.js b/docs/scripts/formattedTSDemos.js index abdf96b6263d12..2973547b58da73 100644 --- a/docs/scripts/formattedTSDemos.js +++ b/docs/scripts/formattedTSDemos.js @@ -55,7 +55,8 @@ async function getFiles(root) { files.push(...(await getFiles(filePath))); } else if ( stat.isFile() && - /\.tsx?$/.test(filePath) && + (/\.tsx?$/.test(filePath) || /\.ts?$/.test(filePath)) && + !filePath.endsWith('types.ts') && !filePath.endsWith('.d.ts') && !ignoreList.some((ignorePath) => filePath.endsWith(path.normalize(ignorePath))) ) { From e41c30ab7353653e656aa3f3bc96dea40204e0cf Mon Sep 17 00:00:00 2001 From: mnajdova Date: Mon, 21 Oct 2024 11:56:13 +0200 Subject: [PATCH 04/17] update codesandbox and stackblitz --- .../components/autocomplete/ListView.js | 122 ------------------ .../components/autocomplete/ListView.tsx | 113 ---------------- docs/src/modules/sandbox/CodeSandbox.ts | 5 +- .../modules/sandbox/FlattenRelativeImports.ts | 5 +- docs/src/modules/sandbox/StackBlitz.ts | 5 +- 5 files changed, 12 insertions(+), 238 deletions(-) delete mode 100644 docs/data/material/components/autocomplete/ListView.js delete mode 100644 docs/data/material/components/autocomplete/ListView.tsx diff --git a/docs/data/material/components/autocomplete/ListView.js b/docs/data/material/components/autocomplete/ListView.js deleted file mode 100644 index 8847a59f6a75eb..00000000000000 --- a/docs/data/material/components/autocomplete/ListView.js +++ /dev/null @@ -1,122 +0,0 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; -import { DataGridPro } from '@mui/x-data-grid-pro'; -import Box from '@mui/material/Box'; -import { useDemoData } from '@mui/x-data-grid-generator'; -import Stack from '@mui/material/Stack'; -import Avatar from '@mui/material/Avatar'; -import Typography from '@mui/material/Typography'; -import Checkbox from '@mui/material/Checkbox'; -import FormControlLabel from '@mui/material/FormControlLabel'; -import IconButton from '@mui/material/IconButton'; -import MessageIcon from '@mui/icons-material/Message'; - -function MessageAction(params) { - const handleMessage = () => { - console.log(`send message to ${params.row.phone}`); - }; - return ( - - - - ); -} - -MessageAction.propTypes = { - /** - * The row model of the row that the current cell belongs to. - */ - row: PropTypes.any.isRequired, -}; - -function ListViewCell(params) { - return ( - - - - - {params.row.name} - - - {params.row.position} - - - - - ); -} - -ListViewCell.propTypes = { - /** - * The row model of the row that the current cell belongs to. - */ - row: PropTypes.any.isRequired, -}; - -const listColDef = { - field: 'listColumn', - renderCell: ListViewCell, -}; - -const VISIBLE_FIELDS = ['avatar', 'name', 'position']; - -export default function ListView() { - const [isListView, setIsListView] = React.useState(true); - - const { data } = useDemoData({ - dataSet: 'Employee', - rowLength: 20, - visibleFields: VISIBLE_FIELDS, - }); - - const columns = React.useMemo(() => { - return [ - ...data.columns, - { - type: 'actions', - field: 'actions', - width: 75, - getActions: (params) => [], - }, - ]; - }, [data.columns]); - - const rowHeight = isListView ? 64 : 52; - - return ( - - setIsListView(event.target.checked)} - /> - } - label="Enable list view" - /> - - - - - ); -} diff --git a/docs/data/material/components/autocomplete/ListView.tsx b/docs/data/material/components/autocomplete/ListView.tsx deleted file mode 100644 index 40239d5a8e41af..00000000000000 --- a/docs/data/material/components/autocomplete/ListView.tsx +++ /dev/null @@ -1,113 +0,0 @@ -import * as React from 'react'; -import { - DataGridPro, - GridRenderCellParams, - GridListColDef, - GridColDef, - GridRowParams, -} from '@mui/x-data-grid-pro'; -import Box from '@mui/material/Box'; -import { useDemoData } from '@mui/x-data-grid-generator'; -import Stack from '@mui/material/Stack'; -import Avatar from '@mui/material/Avatar'; -import Typography from '@mui/material/Typography'; -import Checkbox from '@mui/material/Checkbox'; -import FormControlLabel from '@mui/material/FormControlLabel'; -import IconButton from '@mui/material/IconButton'; -import MessageIcon from '@mui/icons-material/Message'; - -function MessageAction(params: Pick) { - const handleMessage = () => { - console.log(`send message to ${params.row.phone}`); - }; - return ( - - - - ); -} - -function ListViewCell(params: GridRenderCellParams) { - return ( - - - - - {params.row.name} - - - {params.row.position} - - - - - ); -} - -const listColDef: GridListColDef = { - field: 'listColumn', - renderCell: ListViewCell, -}; - -const VISIBLE_FIELDS = ['avatar', 'name', 'position']; - -export default function ListView() { - const [isListView, setIsListView] = React.useState(true); - - const { data } = useDemoData({ - dataSet: 'Employee', - rowLength: 20, - visibleFields: VISIBLE_FIELDS, - }); - - const columns: GridColDef[] = React.useMemo(() => { - return [ - ...data.columns, - { - type: 'actions', - field: 'actions', - width: 75, - getActions: (params) => [], - }, - ]; - }, [data.columns]); - - const rowHeight = isListView ? 64 : 52; - - return ( - - setIsListView(event.target.checked)} - /> - } - label="Enable list view" - /> - - - - - ); -} diff --git a/docs/src/modules/sandbox/CodeSandbox.ts b/docs/src/modules/sandbox/CodeSandbox.ts index 8a4bdc7744a3ba..defbde804ef7f4 100644 --- a/docs/src/modules/sandbox/CodeSandbox.ts +++ b/docs/src/modules/sandbox/CodeSandbox.ts @@ -60,7 +60,10 @@ function createReactApp(demoData: DemoData) { ...acc, // Remove the path and keep the filename [`src/${curr.module.replace(/^.*[\\/]/g, '')}`]: { - content: curr.raw, + content: flattenRelativeImports( + curr.raw, + demoData.relativeModules?.map((file) => file.module), + ), }, }), {}, diff --git a/docs/src/modules/sandbox/FlattenRelativeImports.ts b/docs/src/modules/sandbox/FlattenRelativeImports.ts index a6e3668d71be63..e34b3799281e99 100644 --- a/docs/src/modules/sandbox/FlattenRelativeImports.ts +++ b/docs/src/modules/sandbox/FlattenRelativeImports.ts @@ -3,8 +3,11 @@ export default function flattenRelativeImports(rawCode: string, modulePaths: str modulePaths.forEach((path: string) => { const pathWithoutExtension = path.replace(/\.[a-z]*$/g, ''); // Move the relative import to the current directory - const newPath = `./${pathWithoutExtension.replace(/^.*[\\/]/g, '')}`; + let newPath = `./${pathWithoutExtension.replace(/^.*[\\/]/g, '')}`; newCode = newCode.replace(pathWithoutExtension, newPath); + + // Replace the relative import towards parent directory + newCode = newCode.replace('../', './'); }); return newCode; } diff --git a/docs/src/modules/sandbox/StackBlitz.ts b/docs/src/modules/sandbox/StackBlitz.ts index 558527e34374ed..2658a84fe38f4b 100644 --- a/docs/src/modules/sandbox/StackBlitz.ts +++ b/docs/src/modules/sandbox/StackBlitz.ts @@ -63,7 +63,10 @@ function createReactApp(demoData: DemoData) { (acc, curr) => ({ ...acc, // Remove the path and keep the filename - [`${curr.module.replace(/^.*[\\/]/g, '')}`]: curr.raw, + [`${curr.module.replace(/^.*[\\/]/g, '')}`]: flattenRelativeImports( + curr.raw, + demoData.relativeModules?.map((file) => file.module), + ), }), {}, )), From 8270fb82a3fdfde2b540141a2a1f85ab0150738e Mon Sep 17 00:00:00 2001 From: mnajdova Date: Thu, 24 Oct 2024 11:56:06 +0200 Subject: [PATCH 05/17] fix TS demos --- .../components/autocomplete/autocomplete.md | 2 +- packages/markdown/loader.js | 204 +++++++++--------- 2 files changed, 104 insertions(+), 102 deletions(-) diff --git a/docs/data/material/components/autocomplete/autocomplete.md b/docs/data/material/components/autocomplete/autocomplete.md index eccc8b4b1999f9..9662d05115a574 100644 --- a/docs/data/material/components/autocomplete/autocomplete.md +++ b/docs/data/material/components/autocomplete/autocomplete.md @@ -358,7 +358,7 @@ Search within 10,000 randomly generated options. The list is virtualized thanks The list view feature can be combined with [custom subcomponents](/x/react-data-grid/components/) to provide an improved user experience on small screens. -{{"demo": "ListViewAdvanced.js", "bg": "inline", "maxWidth": 360, "height": 600}} +{{"demo": "ListViewAdvanced.js", "iframe": true, "bg": "inline", "maxWidth": 360, "height": 600}} ## Events diff --git a/packages/markdown/loader.js b/packages/markdown/loader.js index 4e1e6ba8922672..7411caf19c35bc 100644 --- a/packages/markdown/loader.js +++ b/packages/markdown/loader.js @@ -151,8 +151,8 @@ module.exports = async function demoLoader() { * @example detectRelativeImports('ComboBox.js', '', JS', './top100Films') => relativeModules.set('ComboBox.js', new Map([['./top100Films.js', ['JS']]])) */ function detectRelativeImports(demoName, moduleFilepath, variant, importModuleID) { + let relativeModuleFilename = importModuleID; if (importModuleID.startsWith('.')) { - let relativeModuleFilename = importModuleID; const demoMap = relativeModules.get(demoName); // If the moduleID does not end with an extension, or ends with an unsupported extension (e.g. ".styling") we need to resolve it // Fastest way to get a file extension, see: https://stackoverflow.com/a/12900504/ @@ -198,29 +198,7 @@ module.exports = async function demoLoader() { } } } - } - - /** - * @param { module: './top100Films.js', raw: '...' } moduleData - * @param string demoName - * @param ['JS' | 'TS'] variants - * Adds the relative module to the demo's relativeModules object for each of the variants - */ - function addToRelativeModules(moduleData, demoName, variants) { - variants.forEach((variant) => { - if (demos[demoName].relativeModules[variant]) { - // Avoid duplicates - if ( - !demos[demoName].relativeModules[variant].some( - (elem) => elem.module === moduleData.module, - ) - ) { - demos[demoName].relativeModules[variant].push(moduleData); - } - } else { - demos[demoName].relativeModules[variant] = [moduleData]; - } - }); + return relativeModuleFilename; } await Promise.all( @@ -464,92 +442,116 @@ module.exports = async function demoLoader() { const addedModulesRelativeToModulePath = new Set(); await Promise.all( Array.from(relativeModules.get(demoName)).map(async ([relativeModuleID, variants]) => { - let raw = ''; - const relativeModuleFilePath = path.join( - path.dirname(moduleFilepath), - relativeModuleID, - ); - - try { - raw = await fs.readFile(relativeModuleFilePath, { - encoding: 'utf8', - }); - - const importedProcessedModuleIDs = new Set(); - const importedProcessedModulesIDsParents = new Map(); - // Find the relative paths in the relative module - if (relativeModuleID.startsWith('.')) { - extractImports(raw).forEach((importModuleID) => { - // detect relative import - detectRelativeImports( - importModuleID, - relativeModuleFilePath, - 'JS', - importModuleID, - ); - if (importModuleID.startsWith('.')) { - importedProcessedModuleIDs.add(importModuleID); - importedProcessedModulesIDsParents.set(importModuleID, relativeModuleFilePath); - } - }); + for (const variant of variants) { + let raw = ''; + const relativeModuleFilePath = path.join( + path.dirname(moduleFilepath), + relativeModuleID, + ); - if (!addedModulesRelativeToModulePath.has(relativeModuleFilePath)) { - const moduleData = { module: relativeModuleID, raw }; - addToRelativeModules(moduleData, demoName, variants); - addedModulesRelativeToModulePath.add(relativeModuleFilePath); - } - } + try { + raw = await fs.readFile(relativeModuleFilePath, { + encoding: 'utf8', + }); - // iterate recursively over the relative imports - while (importedProcessedModuleIDs.size > 0) { - for (const entry of importedProcessedModuleIDs) { - if (entry.startsWith('.')) { - const jsEntryModuleFilePath = path.join( - path.dirname(importedProcessedModulesIDsParents.get(entry)), - entry + '.js', - ); - const tsEntryModuleFilePath = path.join( - path.dirname(importedProcessedModulesIDsParents.get(entry)), - entry + '.ts', + const importedProcessedModuleIDs = new Set(); + const importedProcessedModulesIDsParents = new Map(); + // Find the relative paths in the relative module + if (relativeModuleID.startsWith('.')) { + extractImports(raw).forEach((importModuleID) => { + // detect relative import + const importModuleIdWithExtension = detectRelativeImports( + importModuleID, + relativeModuleFilePath, + variant, + importModuleID, ); - - let entryModuleFilePath = jsEntryModuleFilePath; - let raw = ''; - let module = entry + '.js'; - try { - raw = await fs.readFile(jsEntryModuleFilePath, { encoding: 'utf8' }); - } catch { - raw = await fs.readFile(tsEntryModuleFilePath, { encoding: 'utf8' }); - module = entry + '.ts'; - entryModuleFilePath = tsEntryModuleFilePath; + if (importModuleID.startsWith('.')) { + importedProcessedModuleIDs.add(importModuleIdWithExtension); + importedProcessedModulesIDsParents.set( + importModuleIdWithExtension, + relativeModuleFilePath, + ); } - - extractImports(raw).forEach((importModuleID) => { - // detect relative import - detectRelativeImports(entry, entryModuleFilePath, 'JS', importModuleID); - if (importModuleID.startsWith('.')) { - importedProcessedModuleIDs.add(importModuleID); - importedProcessedModulesIDsParents.set(importModuleID, entryModuleFilePath); + }); + + if (!addedModulesRelativeToModulePath.has(relativeModuleFilePath)) { + const moduleData = { module: relativeModuleID, raw }; + if (demos[demoName].relativeModules[variant]) { + // Avoid duplicates + if ( + !demos[demoName].relativeModules[variant].some( + (elem) => elem.module === moduleData.module, + ) + ) { + demos[demoName].relativeModules[variant].push(moduleData); + } + } else { + demos[demoName].relativeModules[variant] = [moduleData]; + } + addedModulesRelativeToModulePath.add(relativeModuleFilePath); + } + } + // iterate recursively over the relative imports + while (importedProcessedModuleIDs.size > 0) { + for (const entry of importedProcessedModuleIDs) { + if (entry.startsWith('.')) { + const entryModuleFilePath = path.join( + path.dirname(importedProcessedModulesIDsParents.get(entry)), + entry, + ); + + const raw = await fs.readFile(entryModuleFilePath, { encoding: 'utf8' }); + + extractImports(raw).forEach((importModuleID) => { + // detect relative import + const importModuleIdWithExtension = detectRelativeImports( + entry, + entryModuleFilePath, + variant, + importModuleID, + ); + if (importModuleID.startsWith('.')) { + importedProcessedModuleIDs.add(importModuleIdWithExtension); + importedProcessedModulesIDsParents.set( + importModuleIdWithExtension, + entryModuleFilePath, + ); + } + }); + + if (!addedModulesRelativeToModulePath.has(entryModuleFilePath)) { + const modulePathDirectory = moduleFilepath + .split('/') + .slice(0, -1) + .join('/'); + const moduleData = { + module: '.' + entryModuleFilePath.replace(modulePathDirectory, ''), + raw, + }; + if (demos[demoName].relativeModules[variant]) { + // Avoid duplicates + if ( + !demos[demoName].relativeModules[variant].some( + (elem) => elem.module === moduleData.module, + ) + ) { + demos[demoName].relativeModules[variant].push(moduleData); + } + } else { + demos[demoName].relativeModules[variant] = [moduleData]; + } + addedModulesRelativeToModulePath.add(entryModuleFilePath); } - }); - - if (!addedModulesRelativeToModulePath.has(entryModuleFilePath)) { - const modulePathDirectory = moduleFilepath.split('/').slice(0, -1).join('/'); - const moduleData = { - module: '.' + entryModuleFilePath.replace(modulePathDirectory, ''), - raw, - }; - addToRelativeModules(moduleData, demoName, variants); - addedModulesRelativeToModulePath.add(entryModuleFilePath); } + importedProcessedModuleIDs.delete(entry); } - importedProcessedModuleIDs.delete(entry); } + } catch { + throw new Error( + `Could not find a module for the relative import "${relativeModuleID}" in the demo "${demoName}"`, + ); } - } catch { - throw new Error( - `Could not find a module for the relative import "${relativeModuleID}" in the demo "${demoName}"`, - ); } }), ); From 617e250ee9675640a153dcfd84cf7323ecd6b7a7 Mon Sep 17 00:00:00 2001 From: mnajdova Date: Thu, 24 Oct 2024 12:55:03 +0200 Subject: [PATCH 06/17] fix lint issues --- docs/src/modules/sandbox/FlattenRelativeImports.ts | 2 +- packages/markdown/loader.js | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/docs/src/modules/sandbox/FlattenRelativeImports.ts b/docs/src/modules/sandbox/FlattenRelativeImports.ts index e34b3799281e99..15fb19de815773 100644 --- a/docs/src/modules/sandbox/FlattenRelativeImports.ts +++ b/docs/src/modules/sandbox/FlattenRelativeImports.ts @@ -3,7 +3,7 @@ export default function flattenRelativeImports(rawCode: string, modulePaths: str modulePaths.forEach((path: string) => { const pathWithoutExtension = path.replace(/\.[a-z]*$/g, ''); // Move the relative import to the current directory - let newPath = `./${pathWithoutExtension.replace(/^.*[\\/]/g, '')}`; + const newPath = `./${pathWithoutExtension.replace(/^.*[\\/]/g, '')}`; newCode = newCode.replace(pathWithoutExtension, newPath); // Replace the relative import towards parent directory diff --git a/packages/markdown/loader.js b/packages/markdown/loader.js index 7411caf19c35bc..264e93ffa35123 100644 --- a/packages/markdown/loader.js +++ b/packages/markdown/loader.js @@ -450,6 +450,9 @@ module.exports = async function demoLoader() { ); try { + // We are only iterating trough an array that looks + // like this: ['JS', 'TS'], so it is safe to await + // eslint-disable-next-line no-await-in-loop raw = await fs.readFile(relativeModuleFilePath, { encoding: 'utf8', }); @@ -501,9 +504,12 @@ module.exports = async function demoLoader() { entry, ); - const raw = await fs.readFile(entryModuleFilePath, { encoding: 'utf8' }); + // We are only iterating trough an array that looks + // like this: ['JS', 'TS'], so it is safe to await + // eslint-disable-next-line no-await-in-loop + const rawEntry = await fs.readFile(entryModuleFilePath, { encoding: 'utf8' }); - extractImports(raw).forEach((importModuleID) => { + extractImports(rawEntry).forEach((importModuleID) => { // detect relative import const importModuleIdWithExtension = detectRelativeImports( entry, @@ -526,8 +532,8 @@ module.exports = async function demoLoader() { .slice(0, -1) .join('/'); const moduleData = { - module: '.' + entryModuleFilePath.replace(modulePathDirectory, ''), - raw, + module: `.${entryModuleFilePath.replace(modulePathDirectory, '')}`, + raw: rawEntry, }; if (demos[demoName].relativeModules[variant]) { // Avoid duplicates From b0357d574c230ae0e19a1f3ccd5ad48b5dd4123d Mon Sep 17 00:00:00 2001 From: mnajdova Date: Thu, 24 Oct 2024 14:32:25 +0200 Subject: [PATCH 07/17] cleanup the code --- packages/markdown/loader.js | 47 ++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/packages/markdown/loader.js b/packages/markdown/loader.js index 264e93ffa35123..62a3a88174dba2 100644 --- a/packages/markdown/loader.js +++ b/packages/markdown/loader.js @@ -420,6 +420,27 @@ module.exports = async function demoLoader() { // TS version of the demo doesn't exist. This is fine. } + /** + * Inserts the moduleData into the relativeModules object + * @param {*} moduleData + * @param {*} variant + * @example updateRelativeModules({module: 'constants.js', raw: ... }, 'JS') => demos[demoName].relativeModules[variant].push(moduleData) + */ + function updateRelativeModules(moduleData, variant) { + if (demos[demoName].relativeModules[variant]) { + // Avoid duplicates + if ( + !demos[demoName].relativeModules[variant].some( + (elem) => elem.module === moduleData.module, + ) + ) { + demos[demoName].relativeModules[variant].push(moduleData); + } + } else { + demos[demoName].relativeModules[variant] = [moduleData]; + } + } + /* Map over relative import module IDs and resolve them * while grouping by demo variant * From: @@ -480,18 +501,7 @@ module.exports = async function demoLoader() { if (!addedModulesRelativeToModulePath.has(relativeModuleFilePath)) { const moduleData = { module: relativeModuleID, raw }; - if (demos[demoName].relativeModules[variant]) { - // Avoid duplicates - if ( - !demos[demoName].relativeModules[variant].some( - (elem) => elem.module === moduleData.module, - ) - ) { - demos[demoName].relativeModules[variant].push(moduleData); - } - } else { - demos[demoName].relativeModules[variant] = [moduleData]; - } + updateRelativeModules(moduleData, variant); addedModulesRelativeToModulePath.add(relativeModuleFilePath); } } @@ -535,18 +545,7 @@ module.exports = async function demoLoader() { module: `.${entryModuleFilePath.replace(modulePathDirectory, '')}`, raw: rawEntry, }; - if (demos[demoName].relativeModules[variant]) { - // Avoid duplicates - if ( - !demos[demoName].relativeModules[variant].some( - (elem) => elem.module === moduleData.module, - ) - ) { - demos[demoName].relativeModules[variant].push(moduleData); - } - } else { - demos[demoName].relativeModules[variant] = [moduleData]; - } + updateRelativeModules(moduleData, variant); addedModulesRelativeToModulePath.add(entryModuleFilePath); } } From 886577ebe3c03ae0bd20c8b99bd8a470a00bca3c Mon Sep 17 00:00:00 2001 From: mnajdova Date: Fri, 25 Oct 2024 09:19:10 +0200 Subject: [PATCH 08/17] simplify refexp --- docs/scripts/formattedTSDemos.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/scripts/formattedTSDemos.js b/docs/scripts/formattedTSDemos.js index 2973547b58da73..3994bfa860312c 100644 --- a/docs/scripts/formattedTSDemos.js +++ b/docs/scripts/formattedTSDemos.js @@ -55,7 +55,7 @@ async function getFiles(root) { files.push(...(await getFiles(filePath))); } else if ( stat.isFile() && - (/\.tsx?$/.test(filePath) || /\.ts?$/.test(filePath)) && + /\.tsx?$/.test(filePath) && !filePath.endsWith('types.ts') && !filePath.endsWith('.d.ts') && !ignoreList.some((ignorePath) => filePath.endsWith(path.normalize(ignorePath))) From 5effeec93f71a5f3e7676a9adfe30645361bbe6a Mon Sep 17 00:00:00 2001 From: mnajdova Date: Fri, 25 Oct 2024 09:44:30 +0200 Subject: [PATCH 09/17] add early continue statement --- packages/markdown/loader.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/markdown/loader.js b/packages/markdown/loader.js index 62a3a88174dba2..c96cde3bd6274b 100644 --- a/packages/markdown/loader.js +++ b/packages/markdown/loader.js @@ -470,6 +470,11 @@ module.exports = async function demoLoader() { relativeModuleID, ); + // the file has already been processed + if (addedModulesRelativeToModulePath.has(relativeModuleFilePath)) { + continue; + } + try { // We are only iterating trough an array that looks // like this: ['JS', 'TS'], so it is safe to await From c033e45b12eb9f40c6953ddb3ba4348cee28c76d Mon Sep 17 00:00:00 2001 From: mnajdova Date: Fri, 25 Oct 2024 09:53:20 +0200 Subject: [PATCH 10/17] add TS version of top100Films file --- .../components/autocomplete/top100Films.ts | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 docs/data/material/components/autocomplete/top100Films.ts diff --git a/docs/data/material/components/autocomplete/top100Films.ts b/docs/data/material/components/autocomplete/top100Films.ts new file mode 100644 index 00000000000000..3226dcbc8ba7f3 --- /dev/null +++ b/docs/data/material/components/autocomplete/top100Films.ts @@ -0,0 +1,129 @@ +// Top 100 films as rated by IMDb users. http://www.imdb.com/chart/top +const top100Films = [ + { label: 'The Shawshank Redemption', year: 1994 }, + { label: 'The Godfather', year: 1972 }, + { label: 'The Godfather: Part II', year: 1974 }, + { label: 'The Dark Knight', year: 2008 }, + { label: '12 Angry Men', year: 1957 }, + { label: "Schindler's List", year: 1993 }, + { label: 'Pulp Fiction', year: 1994 }, + { + label: 'The Lord of the Rings: The Return of the King', + year: 2003, + }, + { label: 'The Good, the Bad and the Ugly', year: 1966 }, + { label: 'Fight Club', year: 1999 }, + { + label: 'The Lord of the Rings: The Fellowship of the Ring', + year: 2001, + }, + { + label: 'Star Wars: Episode V - The Empire Strikes Back', + year: 1980, + }, + { label: 'Forrest Gump', year: 1994 }, + { label: 'Inception', year: 2010 }, + { + label: 'The Lord of the Rings: The Two Towers', + year: 2002, + }, + { label: "One Flew Over the Cuckoo's Nest", year: 1975 }, + { label: 'Goodfellas', year: 1990 }, + { label: 'The Matrix', year: 1999 }, + { label: 'Seven Samurai', year: 1954 }, + { + label: 'Star Wars: Episode IV - A New Hope', + year: 1977, + }, + { label: 'City of God', year: 2002 }, + { label: 'Se7en', year: 1995 }, + { label: 'The Silence of the Lambs', year: 1991 }, + { label: "It's a Wonderful Life", year: 1946 }, + { label: 'Life Is Beautiful', year: 1997 }, + { label: 'The Usual Suspects', year: 1995 }, + { label: 'Léon: The Professional', year: 1994 }, + { label: 'Spirited Away', year: 2001 }, + { label: 'Saving Private Ryan', year: 1998 }, + { label: 'Once Upon a Time in the West', year: 1968 }, + { label: 'American History X', year: 1998 }, + { label: 'Interstellar', year: 2014 }, + { label: 'Casablanca', year: 1942 }, + { label: 'City Lights', year: 1931 }, + { label: 'Psycho', year: 1960 }, + { label: 'The Green Mile', year: 1999 }, + { label: 'The Intouchables', year: 2011 }, + { label: 'Modern Times', year: 1936 }, + { label: 'Raiders of the Lost Ark', year: 1981 }, + { label: 'Rear Window', year: 1954 }, + { label: 'The Pianist', year: 2002 }, + { label: 'The Departed', year: 2006 }, + { label: 'Terminator 2: Judgment Day', year: 1991 }, + { label: 'Back to the Future', year: 1985 }, + { label: 'Whiplash', year: 2014 }, + { label: 'Gladiator', year: 2000 }, + { label: 'Memento', year: 2000 }, + { label: 'The Prestige', year: 2006 }, + { label: 'The Lion King', year: 1994 }, + { label: 'Apocalypse Now', year: 1979 }, + { label: 'Alien', year: 1979 }, + { label: 'Sunset Boulevard', year: 1950 }, + { + label: 'Dr. Strangelove or: How I Learned to Stop Worrying and Love the Bomb', + year: 1964, + }, + { label: 'The Great Dictator', year: 1940 }, + { label: 'Cinema Paradiso', year: 1988 }, + { label: 'The Lives of Others', year: 2006 }, + { label: 'Grave of the Fireflies', year: 1988 }, + { label: 'Paths of Glory', year: 1957 }, + { label: 'Django Unchained', year: 2012 }, + { label: 'The Shining', year: 1980 }, + { label: 'WALL·E', year: 2008 }, + { label: 'American Beauty', year: 1999 }, + { label: 'The Dark Knight Rises', year: 2012 }, + { label: 'Princess Mononoke', year: 1997 }, + { label: 'Aliens', year: 1986 }, + { label: 'Oldboy', year: 2003 }, + { label: 'Once Upon a Time in America', year: 1984 }, + { label: 'Witness for the Prosecution', year: 1957 }, + { label: 'Das Boot', year: 1981 }, + { label: 'Citizen Kane', year: 1941 }, + { label: 'North by Northwest', year: 1959 }, + { label: 'Vertigo', year: 1958 }, + { + label: 'Star Wars: Episode VI - Return of the Jedi', + year: 1983, + }, + { label: 'Reservoir Dogs', year: 1992 }, + { label: 'Braveheart', year: 1995 }, + { label: 'M', year: 1931 }, + { label: 'Requiem for a Dream', year: 2000 }, + { label: 'Amélie', year: 2001 }, + { label: 'A Clockwork Orange', year: 1971 }, + { label: 'Like Stars on Earth', year: 2007 }, + { label: 'Taxi Driver', year: 1976 }, + { label: 'Lawrence of Arabia', year: 1962 }, + { label: 'Double Indemnity', year: 1944 }, + { + label: 'Eternal Sunshine of the Spotless Mind', + year: 2004, + }, + { label: 'Amadeus', year: 1984 }, + { label: 'To Kill a Mockingbird', year: 1962 }, + { label: 'Toy Story 3', year: 2010 }, + { label: 'Logan', year: 2017 }, + { label: 'Full Metal Jacket', year: 1987 }, + { label: 'Dangal', year: 2016 }, + { label: 'The Sting', year: 1973 }, + { label: '2001: A Space Odyssey', year: 1968 }, + { label: "Singin' in the Rain", year: 1952 }, + { label: 'Toy Story', year: 1995 }, + { label: 'Bicycle Thieves', year: 1948 }, + { label: 'The Kid', year: 1921 }, + { label: 'Inglourious Basterds', year: 2009 }, + { label: 'Snatch', year: 2000 }, + { label: '3 Idiots', year: 2009 }, + { label: 'Monty Python and the Holy Grail', year: 1975 }, +]; + +export default top100Films; From 2dfdc9a37882f0008a8125a9648b347b3b3511f2 Mon Sep 17 00:00:00 2001 From: mnajdova Date: Fri, 25 Oct 2024 10:16:11 +0200 Subject: [PATCH 11/17] simplify flattenRelativeImporst util --- docs/src/modules/sandbox/CodeSandbox.ts | 10 ++-------- docs/src/modules/sandbox/FlattenRelativeImports.ts | 14 ++------------ docs/src/modules/sandbox/StackBlitz.ts | 10 ++-------- 3 files changed, 6 insertions(+), 28 deletions(-) diff --git a/docs/src/modules/sandbox/CodeSandbox.ts b/docs/src/modules/sandbox/CodeSandbox.ts index defbde804ef7f4..26f51d384a47e2 100644 --- a/docs/src/modules/sandbox/CodeSandbox.ts +++ b/docs/src/modules/sandbox/CodeSandbox.ts @@ -47,10 +47,7 @@ function createReactApp(demoData: DemoData) { content: CRA.getRootIndex(demoData), }, [`src/Demo.${ext}`]: { - content: flattenRelativeImports( - demoData.raw, - demoData.relativeModules?.map((file) => file.module), - ), + content: flattenRelativeImports(demoData.raw), }, // Spread the relative modules ...(demoData.relativeModules && @@ -60,10 +57,7 @@ function createReactApp(demoData: DemoData) { ...acc, // Remove the path and keep the filename [`src/${curr.module.replace(/^.*[\\/]/g, '')}`]: { - content: flattenRelativeImports( - curr.raw, - demoData.relativeModules?.map((file) => file.module), - ), + content: flattenRelativeImports(curr.raw), }, }), {}, diff --git a/docs/src/modules/sandbox/FlattenRelativeImports.ts b/docs/src/modules/sandbox/FlattenRelativeImports.ts index 15fb19de815773..521e43ba6dbc4c 100644 --- a/docs/src/modules/sandbox/FlattenRelativeImports.ts +++ b/docs/src/modules/sandbox/FlattenRelativeImports.ts @@ -1,13 +1,3 @@ -export default function flattenRelativeImports(rawCode: string, modulePaths: string[] = []) { - let newCode = rawCode; - modulePaths.forEach((path: string) => { - const pathWithoutExtension = path.replace(/\.[a-z]*$/g, ''); - // Move the relative import to the current directory - const newPath = `./${pathWithoutExtension.replace(/^.*[\\/]/g, '')}`; - newCode = newCode.replace(pathWithoutExtension, newPath); - - // Replace the relative import towards parent directory - newCode = newCode.replace('../', './'); - }); - return newCode; +export default function flattenRelativeImports(rawCode: string) { + return rawCode.replace(/from (['"])\..*[\/]/g, `from $1./`); } diff --git a/docs/src/modules/sandbox/StackBlitz.ts b/docs/src/modules/sandbox/StackBlitz.ts index 2658a84fe38f4b..5002b015ea93bc 100644 --- a/docs/src/modules/sandbox/StackBlitz.ts +++ b/docs/src/modules/sandbox/StackBlitz.ts @@ -52,10 +52,7 @@ function createReactApp(demoData: DemoData) { const files: Record = { 'index.html': CRA.getHtml(demoData), [`index.${ext}`]: CRA.getRootIndex(demoData), - [`Demo.${ext}`]: flattenRelativeImports( - demoData.raw, - demoData.relativeModules?.map((file) => file.module), - ), + [`Demo.${ext}`]: flattenRelativeImports(demoData.raw), // Spread the relative modules ...(demoData.relativeModules && // Transform the relative modules array into an object @@ -63,10 +60,7 @@ function createReactApp(demoData: DemoData) { (acc, curr) => ({ ...acc, // Remove the path and keep the filename - [`${curr.module.replace(/^.*[\\/]/g, '')}`]: flattenRelativeImports( - curr.raw, - demoData.relativeModules?.map((file) => file.module), - ), + [`${curr.module.replace(/^.*[\\/]/g, '')}`]: flattenRelativeImports(curr.raw), }), {}, )), From c70dce02c08d765bfba4744bd6acbdeff8e3eaba Mon Sep 17 00:00:00 2001 From: mnajdova Date: Fri, 25 Oct 2024 11:18:35 +0200 Subject: [PATCH 12/17] remove ListView demo --- .../autocomplete/ListViewAdvanced.js | 355 ----------------- .../autocomplete/ListViewAdvanced.tsx | 375 ------------------ .../components/autocomplete/autocomplete.md | 6 - .../autocomplete/components/ActionDrawer.js | 157 -------- .../autocomplete/components/ActionDrawer.tsx | 101 ----- .../autocomplete/components/Card.js | 155 -------- .../autocomplete/components/Card.tsx | 70 ---- .../autocomplete/components/DetailsDrawer.js | 220 ---------- .../autocomplete/components/DetailsDrawer.tsx | 158 -------- .../autocomplete/components/Drawer.js | 124 ------ .../autocomplete/components/Drawer.tsx | 97 ----- .../autocomplete/components/FileIcon.js | 68 ---- .../autocomplete/components/FileIcon.tsx | 54 --- .../autocomplete/components/ListCell.js | 149 ------- .../autocomplete/components/ListCell.tsx | 117 ------ .../autocomplete/components/RenameDialog.js | 95 ----- .../autocomplete/components/RenameDialog.tsx | 67 ---- .../autocomplete/components/Toolbar.js | 115 ------ .../autocomplete/components/Toolbar.tsx | 115 ------ .../autocomplete/components/ToolbarAddItem.js | 91 ----- .../components/ToolbarAddItem.tsx | 81 ---- .../autocomplete/components/ToolbarButton.js | 18 - .../autocomplete/components/ToolbarButton.tsx | 8 - .../components/ToolbarColumnsItem.js | 86 ---- .../components/ToolbarColumnsItem.tsx | 83 ---- .../components/ToolbarDensityItem.js | 95 ----- .../components/ToolbarDensityItem.tsx | 94 ----- .../components/ToolbarFilterItem.js | 225 ----------- .../components/ToolbarFilterItem.tsx | 225 ----------- .../components/ToolbarSortItem.js | 101 ----- .../components/ToolbarSortItem.tsx | 99 ----- .../components/autocomplete/constants.js | 15 - .../components/autocomplete/constants.ts | 17 - .../material/components/autocomplete/data.js | 202 ---------- .../material/components/autocomplete/data.ts | 204 ---------- .../material/components/autocomplete/types.ts | 30 -- .../material/components/autocomplete/utils.js | 56 --- .../material/components/autocomplete/utils.ts | 56 --- 38 files changed, 4384 deletions(-) delete mode 100644 docs/data/material/components/autocomplete/ListViewAdvanced.js delete mode 100644 docs/data/material/components/autocomplete/ListViewAdvanced.tsx delete mode 100644 docs/data/material/components/autocomplete/components/ActionDrawer.js delete mode 100644 docs/data/material/components/autocomplete/components/ActionDrawer.tsx delete mode 100644 docs/data/material/components/autocomplete/components/Card.js delete mode 100644 docs/data/material/components/autocomplete/components/Card.tsx delete mode 100644 docs/data/material/components/autocomplete/components/DetailsDrawer.js delete mode 100644 docs/data/material/components/autocomplete/components/DetailsDrawer.tsx delete mode 100644 docs/data/material/components/autocomplete/components/Drawer.js delete mode 100644 docs/data/material/components/autocomplete/components/Drawer.tsx delete mode 100644 docs/data/material/components/autocomplete/components/FileIcon.js delete mode 100644 docs/data/material/components/autocomplete/components/FileIcon.tsx delete mode 100644 docs/data/material/components/autocomplete/components/ListCell.js delete mode 100644 docs/data/material/components/autocomplete/components/ListCell.tsx delete mode 100644 docs/data/material/components/autocomplete/components/RenameDialog.js delete mode 100644 docs/data/material/components/autocomplete/components/RenameDialog.tsx delete mode 100644 docs/data/material/components/autocomplete/components/Toolbar.js delete mode 100644 docs/data/material/components/autocomplete/components/Toolbar.tsx delete mode 100644 docs/data/material/components/autocomplete/components/ToolbarAddItem.js delete mode 100644 docs/data/material/components/autocomplete/components/ToolbarAddItem.tsx delete mode 100644 docs/data/material/components/autocomplete/components/ToolbarButton.js delete mode 100644 docs/data/material/components/autocomplete/components/ToolbarButton.tsx delete mode 100644 docs/data/material/components/autocomplete/components/ToolbarColumnsItem.js delete mode 100644 docs/data/material/components/autocomplete/components/ToolbarColumnsItem.tsx delete mode 100644 docs/data/material/components/autocomplete/components/ToolbarDensityItem.js delete mode 100644 docs/data/material/components/autocomplete/components/ToolbarDensityItem.tsx delete mode 100644 docs/data/material/components/autocomplete/components/ToolbarFilterItem.js delete mode 100644 docs/data/material/components/autocomplete/components/ToolbarFilterItem.tsx delete mode 100644 docs/data/material/components/autocomplete/components/ToolbarSortItem.js delete mode 100644 docs/data/material/components/autocomplete/components/ToolbarSortItem.tsx delete mode 100644 docs/data/material/components/autocomplete/constants.js delete mode 100644 docs/data/material/components/autocomplete/constants.ts delete mode 100644 docs/data/material/components/autocomplete/data.js delete mode 100644 docs/data/material/components/autocomplete/data.ts delete mode 100644 docs/data/material/components/autocomplete/types.ts delete mode 100644 docs/data/material/components/autocomplete/utils.js delete mode 100644 docs/data/material/components/autocomplete/utils.ts diff --git a/docs/data/material/components/autocomplete/ListViewAdvanced.js b/docs/data/material/components/autocomplete/ListViewAdvanced.js deleted file mode 100644 index b27633b6327087..00000000000000 --- a/docs/data/material/components/autocomplete/ListViewAdvanced.js +++ /dev/null @@ -1,355 +0,0 @@ -import * as React from 'react'; -import { - GridActionsCellItem, - useGridApiRef, - DataGridPremium, - gridClasses, -} from '@mui/x-data-grid-premium'; -import EditIcon from '@mui/icons-material/Edit'; -import DeleteIcon from '@mui/icons-material/Delete'; -import Avatar from '@mui/material/Avatar'; -import Stack from '@mui/material/Stack'; -import OpenIcon from '@mui/icons-material/Visibility'; -import useMediaQuery from '@mui/material/useMediaQuery'; -import CSSBaseline from '@mui/material/CssBaseline'; -import { randomId } from '@mui/x-data-grid-generator'; -import { FileIcon } from './components/FileIcon'; -import { DetailsDrawer } from './components/DetailsDrawer'; -import { ListCell } from './components/ListCell'; -import { Toolbar } from './components/Toolbar'; -import { INITIAL_ROWS } from './data'; -import { FILE_TYPES } from './constants'; - -import { formatDate, formatSize, stringAvatar } from './utils'; -import { ActionDrawer } from './components/ActionDrawer'; -import { RenameDialog } from './components/RenameDialog'; - -export default function ListViewAdvanced() { - // This is used only for the example - renders the drawer inside the container - const containerRef = React.useRef(null); - const container = () => containerRef.current; - - const isListView = useMediaQuery('(min-width: 700px)'); - - const apiRef = useGridApiRef(); - - const [rows, setRows] = React.useState(INITIAL_ROWS); - - const [loading, setLoading] = React.useState(false); - - const [overlayState, setOverlayState] = React.useState({ - overlay: null, - params: null, - }); - - const handleCloseOverlay = () => { - setOverlayState({ overlay: null, params: null }); - }; - - const handleDelete = React.useCallback((ids) => { - setRows((prevRows) => prevRows.filter((row) => !ids.includes(row.id))); - }, []); - - const handleUpdate = React.useCallback((id, field, value) => { - setRows((prevRows) => - prevRows.map((row) => - row.id === id - ? { ...row, [field]: value, updatedAt: new Date().toISOString() } - : row, - ), - ); - }, []); - - const handleUpload = React.useCallback((event) => { - if (!event.target.files) { - return; - } - - const file = event.target.files[0]; - const createdAt = new Date().toISOString(); - - const fileType = file.type.split('/')[1]; - - // validate file type - if (!FILE_TYPES.includes(fileType)) { - alert('Invalid file type'); - return; - } - - const row = { - id: randomId(), - name: file.name, - description: '', - type: fileType, - size: file.size, - createdBy: 'Kenan Yusuf', - createdAt, - updatedAt: createdAt, - state: 'pending', - }; - - event.target.value = ''; - - // Add temporary row - setLoading(true); - setRows((prevRows) => [...prevRows, row]); - - // Simulate server response time - const timeout = Math.floor(Math.random() * 3000) + 2000; - setTimeout(() => { - const uploadedRow = { ...row, state: 'uploaded' }; - setRows((prevRows) => - prevRows.map((r) => (r.id === row.id ? uploadedRow : r)), - ); - setOverlayState({ overlay: 'actions', params: { row } }); - setLoading(false); - }, timeout); - }, []); - - const columns = React.useMemo( - () => [ - { - field: 'name', - headerName: 'Name', - width: 350, - editable: true, - hideable: false, - renderCell: (params) => { - return ( - - - {params.value} - - ); - }, - }, - { - field: 'createdBy', - headerName: 'Owner', - width: 200, - renderCell: (params) => { - const avatarProps = stringAvatar(params.value); - return ( - - - {params.value} - - ); - }, - }, - { - field: 'createdAt', - headerName: 'Added', - type: 'date', - width: 200, - valueFormatter: formatDate, - }, - { - field: 'updatedAt', - headerName: 'Modified', - type: 'date', - width: 200, - valueFormatter: formatDate, - }, - { - field: 'type', - headerName: 'Type', - width: 150, - }, - { - field: 'size', - headerName: 'Size', - width: 120, - valueFormatter: formatSize, - }, - { - type: 'actions', - field: 'actions', - resizable: false, - width: 50, - getActions: (params) => [ - } - onClick={() => { - setOverlayState({ overlay: 'actions', params }); - }} - showInMenu - />, - } - onClick={() => - apiRef.current?.startCellEditMode({ - id: params.id, - field: 'name', - }) - } - showInMenu - />, - } - onClick={() => handleDelete([params.id])} - showInMenu - />, - ], - }, - ], - [handleDelete, apiRef], - ); - - const listColDef = React.useMemo( - () => ({ - field: 'listCell', - renderCell: (params) => ( - { - setOverlayState({ overlay: 'actions', params }); - }} - /> - ), - }), - [], - ); - - const getEstimatedRowHeight = () => { - const density = apiRef.current?.state?.density; - - if (isListView) { - switch (density) { - case 'compact': - return 47; - case 'standard': - return 67; - case 'comfortable': - return 97; - default: - return 67; - } - } else { - switch (density) { - case 'compact': - return 47; - case 'standard': - return 55; - case 'comfortable': - return 63; - default: - return 55; - } - } - }; - - const getRowHeight = React.useCallback( - () => (isListView ? 'auto' : undefined), - [isListView], - ); - - return ( - - -
- - setOverlayState({ overlay: 'actions', params }) - } - hideFooterSelectedRowCount - /> - handleUpdate(id, 'description', value)} - onClose={handleCloseOverlay} - /> - - setOverlayState({ overlay: 'details', params: overlayState.params }) - } - onRename={() => - setOverlayState({ overlay: 'rename', params: overlayState.params }) - } - onDelete={(id) => { - handleDelete([id]); - handleCloseOverlay(); - }} - onClose={handleCloseOverlay} - /> - handleUpdate(id, 'name', value)} - onClose={handleCloseOverlay} - /> -
-
- ); -} diff --git a/docs/data/material/components/autocomplete/ListViewAdvanced.tsx b/docs/data/material/components/autocomplete/ListViewAdvanced.tsx deleted file mode 100644 index e7b9c692bededa..00000000000000 --- a/docs/data/material/components/autocomplete/ListViewAdvanced.tsx +++ /dev/null @@ -1,375 +0,0 @@ -import * as React from 'react'; -import { - GridActionsCellItem, - GridColDef, - useGridApiRef, - GridRowParams, - DataGridPremium, - GridRowId, - gridClasses, - GridRowModel, -} from '@mui/x-data-grid-premium'; -import EditIcon from '@mui/icons-material/Edit'; -import DeleteIcon from '@mui/icons-material/Delete'; -import Avatar from '@mui/material/Avatar'; -import Stack from '@mui/material/Stack'; -import OpenIcon from '@mui/icons-material/Visibility'; -import useMediaQuery from '@mui/material/useMediaQuery'; -import CSSBaseline from '@mui/material/CssBaseline'; -import { randomId } from '@mui/x-data-grid-generator'; -import { FileIcon } from './components/FileIcon'; -import { DetailsDrawer } from './components/DetailsDrawer'; -import { ListCell } from './components/ListCell'; -import { Toolbar } from './components/Toolbar'; -import { INITIAL_ROWS } from './data'; -import { FILE_TYPES } from './constants'; -import { RowModel, FileType } from './types'; -import { formatDate, formatSize, stringAvatar } from './utils'; -import { ActionDrawer } from './components/ActionDrawer'; -import { RenameDialog } from './components/RenameDialog'; - -export default function ListViewAdvanced() { - // This is used only for the example - renders the drawer inside the container - const containerRef = React.useRef(null); - const container = () => containerRef.current as HTMLElement; - - const isListView = useMediaQuery('(min-width: 700px)'); - - const apiRef = useGridApiRef(); - - const [rows, setRows] = React.useState[]>(INITIAL_ROWS); - - const [loading, setLoading] = React.useState(false); - - const [overlayState, setOverlayState] = React.useState<{ - overlay: 'actions' | 'details' | 'rename' | null; - params: Pick, 'row'> | null; - }>({ - overlay: null, - params: null, - }); - - const handleCloseOverlay = () => { - setOverlayState({ overlay: null, params: null }); - }; - - const handleDelete = React.useCallback((ids: GridRowId[]) => { - setRows((prevRows) => prevRows.filter((row) => !ids.includes(row.id))); - }, []); - - const handleUpdate = React.useCallback( - ( - id: GridRowId, - field: GridRowParams['columns'][number]['field'], - value: string, - ) => { - setRows((prevRows) => - prevRows.map((row) => - row.id === id - ? { ...row, [field]: value, updatedAt: new Date().toISOString() } - : row, - ), - ); - }, - [], - ); - - const handleUpload = React.useCallback( - (event: React.ChangeEvent) => { - if (!event.target.files) { - return; - } - - const file = event.target.files[0]; - const createdAt = new Date().toISOString(); - - const fileType = file.type.split('/')[1]; - - // validate file type - if (!FILE_TYPES.includes(fileType as FileType)) { - alert('Invalid file type'); - return; - } - - const row: RowModel = { - id: randomId(), - name: file.name, - description: '', - type: fileType as FileType, - size: file.size, - createdBy: 'Kenan Yusuf', - createdAt, - updatedAt: createdAt, - state: 'pending', - }; - - event.target.value = ''; - - // Add temporary row - setLoading(true); - setRows((prevRows) => [...prevRows, row]); - - // Simulate server response time - const timeout = Math.floor(Math.random() * 3000) + 2000; - setTimeout(() => { - const uploadedRow: RowModel = { ...row, state: 'uploaded' }; - setRows((prevRows) => - prevRows.map((r) => (r.id === row.id ? uploadedRow : r)), - ); - setOverlayState({ overlay: 'actions', params: { row } }); - setLoading(false); - }, timeout); - }, - [], - ); - - const columns: GridColDef[] = React.useMemo( - () => [ - { - field: 'name', - headerName: 'Name', - width: 350, - editable: true, - hideable: false, - renderCell: (params) => { - return ( - - - {params.value} - - ); - }, - }, - { - field: 'createdBy', - headerName: 'Owner', - width: 200, - renderCell: (params) => { - const avatarProps = stringAvatar(params.value); - return ( - - - {params.value} - - ); - }, - }, - { - field: 'createdAt', - headerName: 'Added', - type: 'date', - width: 200, - valueFormatter: formatDate, - }, - { - field: 'updatedAt', - headerName: 'Modified', - type: 'date', - width: 200, - valueFormatter: formatDate, - }, - { - field: 'type', - headerName: 'Type', - width: 150, - }, - { - field: 'size', - headerName: 'Size', - width: 120, - valueFormatter: formatSize, - }, - { - type: 'actions', - field: 'actions', - resizable: false, - width: 50, - getActions: (params) => [ - } - onClick={() => { - setOverlayState({ overlay: 'actions', params }); - }} - showInMenu - />, - } - onClick={() => - apiRef.current?.startCellEditMode({ - id: params.id, - field: 'name', - }) - } - showInMenu - />, - } - onClick={() => handleDelete([params.id])} - showInMenu - />, - ], - }, - ], - [handleDelete, apiRef], - ); - - const listColDef: GridColDef = React.useMemo( - () => ({ - field: 'listCell', - renderCell: (params) => ( - { - setOverlayState({ overlay: 'actions', params }); - }} - /> - ), - }), - [], - ); - - const getEstimatedRowHeight = () => { - const density = apiRef.current?.state?.density; - - if (isListView) { - switch (density) { - case 'compact': - return 47; - case 'standard': - return 67; - case 'comfortable': - return 97; - default: - return 67; - } - } else { - switch (density) { - case 'compact': - return 47; - case 'standard': - return 55; - case 'comfortable': - return 63; - default: - return 55; - } - } - }; - - const getRowHeight = React.useCallback( - () => (isListView ? 'auto' : undefined), - [isListView], - ); - - return ( - - -
- - setOverlayState({ overlay: 'actions', params }) - } - hideFooterSelectedRowCount - /> - - handleUpdate(id, 'description', value)} - onClose={handleCloseOverlay} - /> - - - setOverlayState({ overlay: 'details', params: overlayState.params }) - } - onRename={() => - setOverlayState({ overlay: 'rename', params: overlayState.params }) - } - onDelete={(id) => { - handleDelete([id]); - handleCloseOverlay(); - }} - onClose={handleCloseOverlay} - /> - - handleUpdate(id, 'name', value)} - onClose={handleCloseOverlay} - /> -
-
- ); -} diff --git a/docs/data/material/components/autocomplete/autocomplete.md b/docs/data/material/components/autocomplete/autocomplete.md index 9662d05115a574..0f7b7c214ce503 100644 --- a/docs/data/material/components/autocomplete/autocomplete.md +++ b/docs/data/material/components/autocomplete/autocomplete.md @@ -354,12 +354,6 @@ Search within 10,000 randomly generated options. The list is virtualized thanks {{"demo": "Virtualize.js"}} -## Advanced usage - -The list view feature can be combined with [custom subcomponents](/x/react-data-grid/components/) to provide an improved user experience on small screens. - -{{"demo": "ListViewAdvanced.js", "iframe": true, "bg": "inline", "maxWidth": 360, "height": 600}} - ## Events If you would like to prevent the default key handler behavior, you can set the event's `defaultMuiPrevented` property to `true`: diff --git a/docs/data/material/components/autocomplete/components/ActionDrawer.js b/docs/data/material/components/autocomplete/components/ActionDrawer.js deleted file mode 100644 index 244587371e3a78..00000000000000 --- a/docs/data/material/components/autocomplete/components/ActionDrawer.js +++ /dev/null @@ -1,157 +0,0 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; - -import ListItemIcon from '@mui/material/ListItemIcon'; -import ListItemText from '@mui/material/ListItemText'; -import List from '@mui/material/List'; -import ListItem from '@mui/material/ListItem'; -import ListItemButton from '@mui/material/ListItemButton'; -import Stack from '@mui/material/Stack'; -import Typography from '@mui/material/Typography'; -import EditIcon from '@mui/icons-material/Edit'; -import DeleteIcon from '@mui/icons-material/Delete'; -import OpenIcon from '@mui/icons-material/Visibility'; -import { FileIcon } from './FileIcon'; -import { formatDate, formatSize } from '../utils'; -import { Drawer, DrawerHeader } from './Drawer'; - -function DrawerContent(props) { - const { params, onDelete, onPreview, onRename } = props; - return ( - - - - - {params.row.name} - - - {params.row.createdBy} - - - · - - - {formatSize(params.row.size)} - - - - {params.row.updatedAt - ? `Updated ${formatDate(params.row.updatedAt)}` - : `Added ${formatDate(params.row.createdAt)}`} - - - - - - - - - - - Preview - - - - - - - - Rename - - - - onDelete(params.row.id)}> - - - - Delete - - - - - ); -} - -DrawerContent.propTypes = { - onDelete: PropTypes.func.isRequired, - onPreview: PropTypes.func.isRequired, - onRename: PropTypes.func.isRequired, - params: PropTypes.shape({ - row: PropTypes.shape({ - createdAt: PropTypes.string.isRequired, - createdBy: PropTypes.string.isRequired, - description: PropTypes.string.isRequired, - id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, - name: PropTypes.string.isRequired, - size: PropTypes.number.isRequired, - state: PropTypes.oneOf(['pending', 'uploaded']).isRequired, - type: PropTypes.oneOf([ - 'docx', - 'gif', - 'jpeg', - 'jpg', - 'mov', - 'mp4', - 'pdf', - 'png', - 'tiff', - 'txt', - 'webm', - 'webp', - 'zip', - ]).isRequired, - updatedAt: PropTypes.string.isRequired, - }).isRequired, - }).isRequired, -}; - -function ActionDrawer(props) { - const { params, onPreview, onRename, onDelete, ...other } = props; - return ( - - {params && ( - - )} - - ); -} - -ActionDrawer.propTypes = { - onDelete: PropTypes.func.isRequired, - onPreview: PropTypes.func.isRequired, - onRename: PropTypes.func.isRequired, - params: PropTypes.shape({ - row: PropTypes.shape({ - createdAt: PropTypes.string.isRequired, - createdBy: PropTypes.string.isRequired, - description: PropTypes.string.isRequired, - id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, - name: PropTypes.string.isRequired, - size: PropTypes.number.isRequired, - state: PropTypes.oneOf(['pending', 'uploaded']).isRequired, - type: PropTypes.oneOf([ - 'docx', - 'gif', - 'jpeg', - 'jpg', - 'mov', - 'mp4', - 'pdf', - 'png', - 'tiff', - 'txt', - 'webm', - 'webp', - 'zip', - ]).isRequired, - updatedAt: PropTypes.string.isRequired, - }).isRequired, - }), -}; - -export { ActionDrawer }; diff --git a/docs/data/material/components/autocomplete/components/ActionDrawer.tsx b/docs/data/material/components/autocomplete/components/ActionDrawer.tsx deleted file mode 100644 index 533c8cddad5fb1..00000000000000 --- a/docs/data/material/components/autocomplete/components/ActionDrawer.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import * as React from 'react'; -import { GridRowId, GridRowParams } from '@mui/x-data-grid-premium'; -import ListItemIcon from '@mui/material/ListItemIcon'; -import ListItemText from '@mui/material/ListItemText'; -import List from '@mui/material/List'; -import ListItem from '@mui/material/ListItem'; -import ListItemButton from '@mui/material/ListItemButton'; -import Stack from '@mui/material/Stack'; -import Typography from '@mui/material/Typography'; -import EditIcon from '@mui/icons-material/Edit'; -import DeleteIcon from '@mui/icons-material/Delete'; -import OpenIcon from '@mui/icons-material/Visibility'; -import { FileIcon } from './FileIcon'; -import { formatDate, formatSize } from '../utils'; -import { Drawer, DrawerHeader, DrawerProps } from './Drawer'; -import { RowModel } from '../types'; - -interface ActionDrawerProps extends DrawerProps { - params: Pick, 'row'> | null; - onPreview: () => void; - onRename: () => void; - onDelete: (id: GridRowId) => void; -} - -function DrawerContent( - props: { params: Pick, 'row'> } & Pick< - ActionDrawerProps, - 'onDelete' | 'onPreview' | 'onRename' - >, -) { - const { params, onDelete, onPreview, onRename } = props; - return ( - - - - - {params.row.name} - - - {params.row.createdBy} - - - · - - - {formatSize(params.row.size)} - - - - {params.row.updatedAt - ? `Updated ${formatDate(params.row.updatedAt)}` - : `Added ${formatDate(params.row.createdAt)}`} - - - - - - - - - - - Preview - - - - - - - - Rename - - - - onDelete(params.row.id)}> - - - - Delete - - - - - ); -} - -export function ActionDrawer(props: ActionDrawerProps) { - const { params, onPreview, onRename, onDelete, ...other } = props; - return ( - - {params && ( - - )} - - ); -} diff --git a/docs/data/material/components/autocomplete/components/Card.js b/docs/data/material/components/autocomplete/components/Card.js deleted file mode 100644 index a5f52ae73504b2..00000000000000 --- a/docs/data/material/components/autocomplete/components/Card.js +++ /dev/null @@ -1,155 +0,0 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; -import Stack from '@mui/material/Stack'; -import Typography from '@mui/material/Typography'; - -function Card(props) { - const { children, ...other } = props; - return ( - - {children} - - ); -} - -Card.propTypes = { - /** - * The content of the component. - */ - children: PropTypes.node, - /** - * The system prop, which allows defining system overrides as well as additional CSS styles. - */ - sx: PropTypes.oneOfType([ - PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool]), - ), - PropTypes.func, - PropTypes.object, - ]), -}; - -export { Card }; - -function CardMedia(props) { - const { children, ...other } = props; - return ( - - {children} - - ); -} - -CardMedia.propTypes = { - /** - * The content of the component. - */ - children: PropTypes.node, - /** - * The system prop, which allows defining system overrides as well as additional CSS styles. - */ - sx: PropTypes.oneOfType([ - PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool]), - ), - PropTypes.func, - PropTypes.object, - ]), -}; - -export { CardMedia }; - -function CardContent(props) { - const { children, ...other } = props; - return ( - - {children} - - ); -} - -CardContent.propTypes = { - /** - * The content of the component. - */ - children: PropTypes.node, - /** - * The system prop, which allows defining system overrides as well as additional CSS styles. - */ - sx: PropTypes.oneOfType([ - PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool]), - ), - PropTypes.func, - PropTypes.object, - ]), -}; - -export { CardContent }; - -function CardTitle(props) { - const { children, ...other } = props; - return ( - - {children} - - ); -} - -CardTitle.propTypes = { - /** - * The content of the component. - */ - children: PropTypes.node, -}; - -export { CardTitle }; - -function CardDetailList(props) { - const { children, ...other } = props; - return ( - - {children} - - ); -} - -CardDetailList.propTypes = { - /** - * The content of the component. - */ - children: PropTypes.node, -}; - -export { CardDetailList }; - -function CardDetail(props) { - const { children, ...other } = props; - return ( - - {children} - - ); -} - -CardDetail.propTypes = { - /** - * The content of the component. - */ - children: PropTypes.node, -}; - -export { CardDetail }; diff --git a/docs/data/material/components/autocomplete/components/Card.tsx b/docs/data/material/components/autocomplete/components/Card.tsx deleted file mode 100644 index bd0df76f5db159..00000000000000 --- a/docs/data/material/components/autocomplete/components/Card.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import * as React from 'react'; -import Stack, { StackProps } from '@mui/material/Stack'; -import Typography, { TypographyProps } from '@mui/material/Typography'; - -export function Card(props: StackProps) { - const { children, ...other } = props; - return ( - - {children} - - ); -} - -export function CardMedia(props: StackProps) { - const { children, ...other } = props; - return ( - - {children} - - ); -} - -export function CardContent(props: StackProps) { - const { children, ...other } = props; - return ( - - {children} - - ); -} - -export function CardTitle(props: TypographyProps) { - const { children, ...other } = props; - return ( - - {children} - - ); -} - -export function CardDetailList(props: StackProps) { - const { children, ...other } = props; - return ( - - {children} - - ); -} - -export function CardDetail(props: TypographyProps) { - const { children, ...other } = props; - return ( - - {children} - - ); -} diff --git a/docs/data/material/components/autocomplete/components/DetailsDrawer.js b/docs/data/material/components/autocomplete/components/DetailsDrawer.js deleted file mode 100644 index 2a990bf2c2e3b2..00000000000000 --- a/docs/data/material/components/autocomplete/components/DetailsDrawer.js +++ /dev/null @@ -1,220 +0,0 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; - -import Divider from '@mui/material/Divider'; -import Stack from '@mui/material/Stack'; -import Typography from '@mui/material/Typography'; -import TextField from '@mui/material/TextField'; -import Avatar from '@mui/material/Avatar'; -import Box from '@mui/material/Box'; -import Button from '@mui/material/Button'; -import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; -import { Drawer, DrawerHeader } from './Drawer'; -import { FileIcon } from './FileIcon'; -import { formatDate, formatSize, stringAvatar } from '../utils'; - -function Thumbnail() { - return ( - ({ - aspectRatio: '16/9', - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - color: 'text.secondary', - borderRadius: 2, - gap: 1, - backgroundColor: 'grey.200', - ...theme.applyStyles('dark', { - backgroundColor: 'grey.800', - }), - })} - > - - - No preview available - - - ); -} - -function DrawerContent(props) { - const { params, onDescriptionChange, onClose } = props; - const [description, setDescription] = React.useState(params.row.description || ''); - const avatarProps = stringAvatar(params.row.createdBy); - - const handleSave = (event) => { - onDescriptionChange(params.row.id, description); - onClose(event); - }; - - return ( - - - - {params.row.name} - - - - - - setDescription(event.target.value)} - sx={{ mt: 1 }} - multiline - /> - - - - Type - - {params.row.type} - - - - - Size - - {formatSize(params.row.size)} - - - - - Created - - {formatDate(params.row.createdAt)} - - - - - Modified - - {formatDate(params.row.updatedAt)} - - - - - Owner - - - - - {params.row.createdBy} - - - - ); -} - -DrawerContent.propTypes = { - /** - * Callback fired when the component requests to be closed. - * - * @param {React.SyntheticEvent<{}>} event The event source of the callback. - */ - onClose: PropTypes.func.isRequired, - onDescriptionChange: PropTypes.func.isRequired, - params: PropTypes.shape({ - row: PropTypes.shape({ - createdAt: PropTypes.string.isRequired, - createdBy: PropTypes.string.isRequired, - description: PropTypes.string.isRequired, - id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, - name: PropTypes.string.isRequired, - size: PropTypes.number.isRequired, - state: PropTypes.oneOf(['pending', 'uploaded']).isRequired, - type: PropTypes.oneOf([ - 'docx', - 'gif', - 'jpeg', - 'jpg', - 'mov', - 'mp4', - 'pdf', - 'png', - 'tiff', - 'txt', - 'webm', - 'webp', - 'zip', - ]).isRequired, - updatedAt: PropTypes.string.isRequired, - }).isRequired, - }).isRequired, -}; - -function DetailsDrawer(props) { - const { params, listView, onDescriptionChange, onClose, ...other } = props; - return ( - - {params && ( - - )} - - ); -} - -DetailsDrawer.propTypes = { - listView: PropTypes.bool.isRequired, - /** - * Callback fired when the component requests to be closed. - * - * @param {React.SyntheticEvent<{}>} event The event source of the callback. - */ - onClose: PropTypes.func.isRequired, - onDescriptionChange: PropTypes.func.isRequired, - params: PropTypes.shape({ - row: PropTypes.shape({ - createdAt: PropTypes.string.isRequired, - createdBy: PropTypes.string.isRequired, - description: PropTypes.string.isRequired, - id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, - name: PropTypes.string.isRequired, - size: PropTypes.number.isRequired, - state: PropTypes.oneOf(['pending', 'uploaded']).isRequired, - type: PropTypes.oneOf([ - 'docx', - 'gif', - 'jpeg', - 'jpg', - 'mov', - 'mp4', - 'pdf', - 'png', - 'tiff', - 'txt', - 'webm', - 'webp', - 'zip', - ]).isRequired, - updatedAt: PropTypes.string.isRequired, - }).isRequired, - }), -}; - -export { DetailsDrawer }; diff --git a/docs/data/material/components/autocomplete/components/DetailsDrawer.tsx b/docs/data/material/components/autocomplete/components/DetailsDrawer.tsx deleted file mode 100644 index 6e4f2545dfeb1a..00000000000000 --- a/docs/data/material/components/autocomplete/components/DetailsDrawer.tsx +++ /dev/null @@ -1,158 +0,0 @@ -import * as React from 'react'; -import { GridRowId, GridRowParams } from '@mui/x-data-grid-premium'; -import Divider from '@mui/material/Divider'; -import Stack from '@mui/material/Stack'; -import Typography from '@mui/material/Typography'; -import TextField from '@mui/material/TextField'; -import Avatar from '@mui/material/Avatar'; -import Box from '@mui/material/Box'; -import Button from '@mui/material/Button'; -import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; -import { Drawer, DrawerHeader, DrawerProps } from './Drawer'; -import { FileIcon } from './FileIcon'; -import { formatDate, formatSize, stringAvatar } from '../utils'; -import { RowModel } from '../types'; - -interface DetailsDrawerProps extends DrawerProps { - params: Pick, 'row'> | null; - listView: boolean; - onDescriptionChange: (id: GridRowId, value: string) => void; -} - -function Thumbnail() { - return ( - ({ - aspectRatio: '16/9', - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - color: 'text.secondary', - borderRadius: 2, - gap: 1, - backgroundColor: 'grey.200', - ...theme.applyStyles('dark', { - backgroundColor: 'grey.800', - }), - })} - > - - - No preview available - - - ); -} - -function DrawerContent( - props: { params: Pick, 'row'> } & Pick< - DetailsDrawerProps, - 'onDescriptionChange' | 'onClose' - >, -) { - const { params, onDescriptionChange, onClose } = props; - const [description, setDescription] = React.useState(params.row.description || ''); - const avatarProps = stringAvatar(params.row.createdBy); - - const handleSave = (event: React.MouseEvent) => { - onDescriptionChange(params.row.id, description); - onClose(event); - }; - - return ( - - - - {params.row.name} - - - - - - - setDescription(event.target.value)} - sx={{ mt: 1 }} - multiline - /> - - - - - - Type - - {params.row.type} - - - - - Size - - {formatSize(params.row.size)} - - - - - Created - - {formatDate(params.row.createdAt)} - - - - - Modified - - {formatDate(params.row.updatedAt)} - - - - - - Owner - - - - - {params.row.createdBy} - - - - ); -} - -export function DetailsDrawer(props: DetailsDrawerProps) { - const { params, listView, onDescriptionChange, onClose, ...other } = props; - return ( - - {params && ( - - )} - - ); -} diff --git a/docs/data/material/components/autocomplete/components/Drawer.js b/docs/data/material/components/autocomplete/components/Drawer.js deleted file mode 100644 index ec9c3ffa3a8d88..00000000000000 --- a/docs/data/material/components/autocomplete/components/Drawer.js +++ /dev/null @@ -1,124 +0,0 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; -import MUISwipeableDrawer from '@mui/material/SwipeableDrawer'; -import Box from '@mui/material/Box'; -import Stack from '@mui/material/Stack'; -import Paper from '@mui/material/Paper'; -import { useMediaQuery } from '@mui/system'; - -function SwipeIndicator() { - return ( - - - - ); -} - -function DrawerHeader(props) { - const { children, ...other } = props; - - return ( - - - {children} - - - ); -} - -DrawerHeader.propTypes = { - /** - * The content of the component. - */ - children: PropTypes.node, -}; - -export { DrawerHeader }; - -function Drawer(props) { - const { children, anchor, width = 320, container, ...other } = props; - const isBottomDrawer = anchor === 'bottom'; - const isTouch = useMediaQuery('(hover: none)'); - - return ( - {}} // required by SwipeableDrawer but not used in this demo - > - {isTouch && isBottomDrawer && } - {children} - - ); -} - -Drawer.propTypes = { - /** - * Side from which the drawer will appear. - * @default 'left' - */ - anchor: PropTypes.oneOf(['bottom', 'left', 'right', 'top']), - /** - * The content of the component. - */ - children: PropTypes.node, - /** - * An HTML element or function that returns one. - * The `container` will have the portal children appended to it. - * - * You can also provide a callback, which is called in a React layout effect. - * This lets you set the container from a ref, and also makes server-side rendering possible. - * - * By default, it uses the body of the top-level document object, - * so it's simply `document.body` most of the time. - */ - container: PropTypes.func, - width: PropTypes.number, -}; - -export { Drawer }; diff --git a/docs/data/material/components/autocomplete/components/Drawer.tsx b/docs/data/material/components/autocomplete/components/Drawer.tsx deleted file mode 100644 index a859781e4417d2..00000000000000 --- a/docs/data/material/components/autocomplete/components/Drawer.tsx +++ /dev/null @@ -1,97 +0,0 @@ -import * as React from 'react'; -import MUISwipeableDrawer, { - SwipeableDrawerProps as MUISwipeableDrawerProps, -} from '@mui/material/SwipeableDrawer'; -import Box from '@mui/material/Box'; -import Stack, { StackProps } from '@mui/material/Stack'; -import Paper from '@mui/material/Paper'; -import { useMediaQuery } from '@mui/system'; - -function SwipeIndicator() { - return ( - - - - ); -} - -export interface DrawerHeaderProps extends StackProps {} - -export function DrawerHeader(props: DrawerHeaderProps) { - const { children, ...other } = props; - - return ( - - - {children} - - - ); -} - -export interface DrawerProps extends Omit { - width?: number; - container?: () => HTMLElement; -} - -export function Drawer(props: DrawerProps) { - const { children, anchor, width = 320, container, ...other } = props; - const isBottomDrawer = anchor === 'bottom'; - const isTouch = useMediaQuery('(hover: none)'); - - return ( - {}} // required by SwipeableDrawer but not used in this demo - > - {isTouch && isBottomDrawer && } - {children} - - ); -} diff --git a/docs/data/material/components/autocomplete/components/FileIcon.js b/docs/data/material/components/autocomplete/components/FileIcon.js deleted file mode 100644 index 24d70c875a3ffa..00000000000000 --- a/docs/data/material/components/autocomplete/components/FileIcon.js +++ /dev/null @@ -1,68 +0,0 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; -import SvgIcon from '@mui/material/SvgIcon'; -import TextSnippetIcon from '@mui/icons-material/TextSnippet'; -import VideocamIcon from '@mui/icons-material/Videocam'; -import ImageIcon from '@mui/icons-material/Image'; -import FolderZipIcon from '@mui/icons-material/FolderZip'; - -const FILE_TYPE_ICONS = { - video: { - component: VideocamIcon, - color: 'error', - }, - image: { - component: ImageIcon, - color: 'error', - }, - document: { - component: TextSnippetIcon, - color: 'primary', - }, - archive: { - component: FolderZipIcon, - color: 'inherit', - }, -}; - -const FILE_ICON = { - pdf: FILE_TYPE_ICONS.document, - docx: FILE_TYPE_ICONS.document, - txt: FILE_TYPE_ICONS.document, - mp4: FILE_TYPE_ICONS.video, - mov: FILE_TYPE_ICONS.video, - webm: FILE_TYPE_ICONS.video, - jpg: FILE_TYPE_ICONS.image, - jpeg: FILE_TYPE_ICONS.image, - png: FILE_TYPE_ICONS.image, - gif: FILE_TYPE_ICONS.image, - tiff: FILE_TYPE_ICONS.image, - webp: FILE_TYPE_ICONS.image, - zip: FILE_TYPE_ICONS.archive, -}; - -function FileIcon(props) { - const { type } = props; - const iconProps = FILE_ICON[type]; - return ; -} - -FileIcon.propTypes = { - type: PropTypes.oneOf([ - 'docx', - 'gif', - 'jpeg', - 'jpg', - 'mov', - 'mp4', - 'pdf', - 'png', - 'tiff', - 'txt', - 'webm', - 'webp', - 'zip', - ]).isRequired, -}; - -export { FileIcon }; diff --git a/docs/data/material/components/autocomplete/components/FileIcon.tsx b/docs/data/material/components/autocomplete/components/FileIcon.tsx deleted file mode 100644 index ac70cced33bf7a..00000000000000 --- a/docs/data/material/components/autocomplete/components/FileIcon.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import * as React from 'react'; -import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon'; -import TextSnippetIcon from '@mui/icons-material/TextSnippet'; -import VideocamIcon from '@mui/icons-material/Videocam'; -import ImageIcon from '@mui/icons-material/Image'; -import FolderZipIcon from '@mui/icons-material/FolderZip'; -import { FileType } from '../types'; - -const FILE_TYPE_ICONS = { - video: { - component: VideocamIcon, - color: 'error', - }, - image: { - component: ImageIcon, - color: 'error', - }, - document: { - component: TextSnippetIcon, - color: 'primary', - }, - archive: { - component: FolderZipIcon, - color: 'inherit', - }, -} satisfies Record< - string, - { component: React.ElementType; color: SvgIconProps['color'] } ->; - -const FILE_ICON: Record< - FileType, - { component: React.ElementType; color: SvgIconProps['color'] } -> = { - pdf: FILE_TYPE_ICONS.document, - docx: FILE_TYPE_ICONS.document, - txt: FILE_TYPE_ICONS.document, - mp4: FILE_TYPE_ICONS.video, - mov: FILE_TYPE_ICONS.video, - webm: FILE_TYPE_ICONS.video, - jpg: FILE_TYPE_ICONS.image, - jpeg: FILE_TYPE_ICONS.image, - png: FILE_TYPE_ICONS.image, - gif: FILE_TYPE_ICONS.image, - tiff: FILE_TYPE_ICONS.image, - webp: FILE_TYPE_ICONS.image, - zip: FILE_TYPE_ICONS.archive, -}; - -export function FileIcon(props: SvgIconProps & { type: FileType }) { - const { type } = props; - const iconProps = FILE_ICON[type]; - return ; -} diff --git a/docs/data/material/components/autocomplete/components/ListCell.js b/docs/data/material/components/autocomplete/components/ListCell.js deleted file mode 100644 index 0e2d0407ef98e3..00000000000000 --- a/docs/data/material/components/autocomplete/components/ListCell.js +++ /dev/null @@ -1,149 +0,0 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; -import { - gridColumnVisibilityModelSelector, - gridDensitySelector, - useGridApiContext, - useGridSelector, -} from '@mui/x-data-grid-premium'; -import IconButton from '@mui/material/IconButton'; -import Box from '@mui/material/Box'; -import GridMoreVertIcon from '@mui/icons-material/MoreVert'; -import { - Card, - CardContent, - CardDetailList, - CardDetail, - CardTitle, - CardMedia, -} from './Card'; -import { FileIcon } from './FileIcon'; -import { formatDate, formatSize } from '../utils'; - -const ICON_SIZE_BY_DENSITY = { - compact: 24, - standard: 32, - comfortable: 16, -}; - -function Thumbnail(props) { - const { fileIcon } = props; - return ( - ({ - position: 'relative', - borderRadius: 1, - width: 64, - height: 64, - overflow: 'hidden', - backgroundColor: 'grey.200', - ...theme.applyStyles('dark', { - backgroundColor: 'grey.800', - }), - })} - > - - {fileIcon} - - - ); -} - -Thumbnail.propTypes = { - fileIcon: PropTypes.node, -}; - -function ListCell(props) { - const { onOpenActions, ...params } = props; - const apiRef = useGridApiContext(); - const density = useGridSelector(apiRef, gridDensitySelector); - const columnVisibilityModel = useGridSelector( - apiRef, - gridColumnVisibilityModelSelector, - ); - - const showCreatedBy = columnVisibilityModel.createdBy !== false; - const showSize = columnVisibilityModel.size !== false; - const showCreatedAt = columnVisibilityModel.createdAt !== false; - const showUpdatedAt = columnVisibilityModel.updatedAt !== false; - const showThumbnail = density === 'comfortable'; - - const icon = ( - - ); - - return ( - - {showThumbnail ? : icon} - - {params.row.name} - {density !== 'compact' && (showCreatedBy || showSize) && ( - - {showCreatedBy && {params.row.createdBy}} - {showSize && {formatSize(params.row.size)}} - - )} - {density === 'comfortable' && (showCreatedAt || showUpdatedAt) && ( - - {showUpdatedAt && `Updated ${formatDate(params.row.updatedAt)}`} - - )} - - - { - event.stopPropagation(); - onOpenActions(); - }} - sx={{ mr: -0.75 }} - > - - - - ); -} - -ListCell.propTypes = { - onOpenActions: PropTypes.func.isRequired, - /** - * The row model of the row that the current cell belongs to. - */ - row: PropTypes.shape({ - createdAt: PropTypes.string.isRequired, - createdBy: PropTypes.string.isRequired, - description: PropTypes.string.isRequired, - id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, - name: PropTypes.string.isRequired, - size: PropTypes.number.isRequired, - state: PropTypes.oneOf(['pending', 'uploaded']).isRequired, - type: PropTypes.oneOf([ - 'docx', - 'gif', - 'jpeg', - 'jpg', - 'mov', - 'mp4', - 'pdf', - 'png', - 'tiff', - 'txt', - 'webm', - 'webp', - 'zip', - ]).isRequired, - updatedAt: PropTypes.string.isRequired, - }).isRequired, -}; - -export { ListCell }; diff --git a/docs/data/material/components/autocomplete/components/ListCell.tsx b/docs/data/material/components/autocomplete/components/ListCell.tsx deleted file mode 100644 index 250d5b82c2178a..00000000000000 --- a/docs/data/material/components/autocomplete/components/ListCell.tsx +++ /dev/null @@ -1,117 +0,0 @@ -import * as React from 'react'; -import { - gridColumnVisibilityModelSelector, - GridDensity, - gridDensitySelector, - GridRenderCellParams, - useGridApiContext, - useGridSelector, -} from '@mui/x-data-grid-premium'; -import IconButton from '@mui/material/IconButton'; -import Box from '@mui/material/Box'; -import GridMoreVertIcon from '@mui/icons-material/MoreVert'; -import { - Card, - CardContent, - CardDetailList, - CardDetail, - CardTitle, - CardMedia, -} from './Card'; -import { FileIcon } from './FileIcon'; -import { formatDate, formatSize } from '../utils'; -import { RowModel } from '../types'; - -interface ListCellProps extends GridRenderCellParams { - onOpenActions: () => void; -} - -const ICON_SIZE_BY_DENSITY: Record = { - compact: 24, - standard: 32, - comfortable: 16, -}; - -function Thumbnail(props: { fileIcon: React.ReactNode }) { - const { fileIcon } = props; - return ( - ({ - position: 'relative', - borderRadius: 1, - width: 64, - height: 64, - overflow: 'hidden', - backgroundColor: 'grey.200', - ...theme.applyStyles('dark', { - backgroundColor: 'grey.800', - }), - })} - > - - {fileIcon} - - - ); -} - -export function ListCell(props: ListCellProps) { - const { onOpenActions, ...params } = props; - const apiRef = useGridApiContext(); - const density = useGridSelector(apiRef, gridDensitySelector); - const columnVisibilityModel = useGridSelector( - apiRef, - gridColumnVisibilityModelSelector, - ); - - const showCreatedBy = columnVisibilityModel.createdBy !== false; - const showSize = columnVisibilityModel.size !== false; - const showCreatedAt = columnVisibilityModel.createdAt !== false; - const showUpdatedAt = columnVisibilityModel.updatedAt !== false; - const showThumbnail = density === 'comfortable'; - - const icon = ( - - ); - - return ( - - {showThumbnail ? : icon} - - {params.row.name} - {density !== 'compact' && (showCreatedBy || showSize) && ( - - {showCreatedBy && {params.row.createdBy}} - {showSize && {formatSize(params.row.size)}} - - )} - {density === 'comfortable' && (showCreatedAt || showUpdatedAt) && ( - - {showUpdatedAt && `Updated ${formatDate(params.row.updatedAt)}`} - - )} - - - { - event.stopPropagation(); - onOpenActions(); - }} - sx={{ mr: -0.75 }} - > - - - - ); -} diff --git a/docs/data/material/components/autocomplete/components/RenameDialog.js b/docs/data/material/components/autocomplete/components/RenameDialog.js deleted file mode 100644 index 17815877da6b89..00000000000000 --- a/docs/data/material/components/autocomplete/components/RenameDialog.js +++ /dev/null @@ -1,95 +0,0 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; - -import Dialog from '@mui/material/Dialog'; -import DialogTitle from '@mui/material/DialogTitle'; -import DialogContent from '@mui/material/DialogContent'; -import DialogActions from '@mui/material/DialogActions'; -import Button from '@mui/material/Button'; -import TextField from '@mui/material/TextField'; - -function RenameDialog(props) { - const { params, open, container, onSave, onClose } = props; - - const handleSave = (event) => { - event.preventDefault(); - - const formData = new FormData(event.currentTarget); - const value = formData.get('name'); - - onSave(params.row.id, value); - - onClose(); - }; - - return ( - - {params && ( - - Rename file - - - - - - - - - )} - - ); -} - -RenameDialog.propTypes = { - container: PropTypes.func, - onClose: PropTypes.func.isRequired, - onSave: PropTypes.func.isRequired, - open: PropTypes.bool.isRequired, - params: PropTypes.shape({ - row: PropTypes.shape({ - createdAt: PropTypes.string.isRequired, - createdBy: PropTypes.string.isRequired, - description: PropTypes.string.isRequired, - id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, - name: PropTypes.string.isRequired, - size: PropTypes.number.isRequired, - state: PropTypes.oneOf(['pending', 'uploaded']).isRequired, - type: PropTypes.oneOf([ - 'docx', - 'gif', - 'jpeg', - 'jpg', - 'mov', - 'mp4', - 'pdf', - 'png', - 'tiff', - 'txt', - 'webm', - 'webp', - 'zip', - ]).isRequired, - updatedAt: PropTypes.string.isRequired, - }).isRequired, - }), -}; - -export { RenameDialog }; diff --git a/docs/data/material/components/autocomplete/components/RenameDialog.tsx b/docs/data/material/components/autocomplete/components/RenameDialog.tsx deleted file mode 100644 index 670e77c81ecd38..00000000000000 --- a/docs/data/material/components/autocomplete/components/RenameDialog.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import * as React from 'react'; -import { GridRowId, GridRowParams } from '@mui/x-data-grid-premium'; -import Dialog from '@mui/material/Dialog'; -import DialogTitle from '@mui/material/DialogTitle'; -import DialogContent from '@mui/material/DialogContent'; -import DialogActions from '@mui/material/DialogActions'; -import Button from '@mui/material/Button'; -import TextField from '@mui/material/TextField'; -import { RowModel } from '../types'; - -export interface RenameDialogProps { - params: Pick, 'row'> | null; - open: boolean; - container?: () => HTMLElement; - onSave: (id: GridRowId, value: string) => void; - onClose: () => void; -} - -export function RenameDialog(props: RenameDialogProps) { - const { params, open, container, onSave, onClose } = props; - - const handleSave = (event: React.FormEvent) => { - event.preventDefault(); - - const formData = new FormData(event.currentTarget); - const value = formData.get('name') as string; - - onSave(params!.row.id, value); - - onClose(); - }; - - return ( - - {params && ( - - Rename file - - - - - - - - - )} - - ); -} diff --git a/docs/data/material/components/autocomplete/components/Toolbar.js b/docs/data/material/components/autocomplete/components/Toolbar.js deleted file mode 100644 index 2034a17a823632..00000000000000 --- a/docs/data/material/components/autocomplete/components/Toolbar.js +++ /dev/null @@ -1,115 +0,0 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; -import { - GridClearIcon, - GridDeleteIcon, - GridToolbarContainer, - GridToolbarQuickFilter, - selectedGridRowsSelector, - useGridApiContext, - useGridSelector, -} from '@mui/x-data-grid-premium'; -import Box from '@mui/material/Box'; -import Typography from '@mui/material/Typography'; -import { outlinedInputClasses } from '@mui/material/OutlinedInput'; -import { iconButtonClasses } from '@mui/material/IconButton'; -import { ToolbarAddItem } from './ToolbarAddItem'; -import { ToolbarColumnsItem } from './ToolbarColumnsItem'; -import { ToolbarSortItem } from './ToolbarSortItem'; -import { ToolbarDensityItem } from './ToolbarDensityItem'; -import { ToolbarFilterItem } from './ToolbarFilterItem'; -import { ToolbarButton } from './ToolbarButton'; - -function Toolbar(props) { - const { listView = false, container, handleUpload, handleDelete } = props; - const apiRef = useGridApiContext(); - const selectedRows = useGridSelector(apiRef, selectedGridRowsSelector); - const selectionCount = selectedRows.size; - const showSelectionOptions = selectionCount > 0; - - const handleClearSelection = () => { - apiRef.current.setRowSelectionModel([]); - }; - - const handleDeleteSelectedRows = () => { - handleClearSelection(); - handleDelete?.(Array.from(selectedRows.keys())); - }; - - const itemProps = { - listView, - container, - }; - - return ( - - {showSelectionOptions ? ( - - - - - - {selectionCount} selected - - - - - - ) : ( - - - - - - - - - - - - )} - - ); -} - -Toolbar.propTypes = { - container: PropTypes.func, - handleDelete: PropTypes.func, - handleUpload: PropTypes.func, - listView: PropTypes.bool, -}; - -export { Toolbar }; diff --git a/docs/data/material/components/autocomplete/components/Toolbar.tsx b/docs/data/material/components/autocomplete/components/Toolbar.tsx deleted file mode 100644 index 62980799d4b291..00000000000000 --- a/docs/data/material/components/autocomplete/components/Toolbar.tsx +++ /dev/null @@ -1,115 +0,0 @@ -import * as React from 'react'; -import { - GridClearIcon, - GridDeleteIcon, - GridRowId, - GridToolbarContainer, - GridToolbarProps, - GridToolbarQuickFilter, - selectedGridRowsSelector, - useGridApiContext, - useGridSelector, -} from '@mui/x-data-grid-premium'; -import Box from '@mui/material/Box'; -import Typography from '@mui/material/Typography'; -import { outlinedInputClasses } from '@mui/material/OutlinedInput'; -import { iconButtonClasses } from '@mui/material/IconButton'; -import { ToolbarAddItem } from './ToolbarAddItem'; -import { ToolbarColumnsItem } from './ToolbarColumnsItem'; -import { ToolbarSortItem } from './ToolbarSortItem'; -import { ToolbarDensityItem } from './ToolbarDensityItem'; -import { ToolbarFilterItem } from './ToolbarFilterItem'; -import { ToolbarButton } from './ToolbarButton'; -import { DrawerProps } from './Drawer'; - -export interface ToolbarProps extends GridToolbarProps { - container?: DrawerProps['container']; - listView?: boolean; - handleDelete?: (ids: GridRowId[]) => void; - handleUpload?: (event: React.ChangeEvent) => void; -} - -export function Toolbar(props: ToolbarProps) { - const { listView = false, container, handleUpload, handleDelete } = props; - const apiRef = useGridApiContext(); - const selectedRows = useGridSelector(apiRef, selectedGridRowsSelector); - const selectionCount = selectedRows.size; - const showSelectionOptions = selectionCount > 0; - - const handleClearSelection = () => { - apiRef.current.setRowSelectionModel([]); - }; - - const handleDeleteSelectedRows = () => { - handleClearSelection(); - handleDelete?.(Array.from(selectedRows.keys())); - }; - - const itemProps = { - listView, - container, - }; - - return ( - - {showSelectionOptions ? ( - - - - - - {selectionCount} selected - - - - - - ) : ( - - - - - - - - - - - - )} - - ); -} diff --git a/docs/data/material/components/autocomplete/components/ToolbarAddItem.js b/docs/data/material/components/autocomplete/components/ToolbarAddItem.js deleted file mode 100644 index b903b8df60af4c..00000000000000 --- a/docs/data/material/components/autocomplete/components/ToolbarAddItem.js +++ /dev/null @@ -1,91 +0,0 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; -import AddIcon from '@mui/icons-material/Add'; -import CloudUploadIcon from '@mui/icons-material/CloudUpload'; -import NewFolderIcon from '@mui/icons-material/CreateNewFolder'; -import List from '@mui/material/List'; -import ListItem from '@mui/material/ListItem'; -import ListItemButton from '@mui/material/ListItemButton'; -import ListItemIcon from '@mui/material/ListItemIcon'; -import ListItemText from '@mui/material/ListItemText'; -import Typography from '@mui/material/Typography'; - -import { ToolbarButton } from './ToolbarButton'; -import { Drawer, DrawerHeader } from './Drawer'; - -const ListItemUploadButton = React.forwardRef( - function ListItemUploadButton(props, ref) { - const { children, ...other } = props; - return ( - - {children} - - ); - }, -); - -ListItemUploadButton.propTypes = { - /** - * The content of the component. - */ - children: PropTypes.node, -}; - -function ToolbarAddItem(props) { - const { container } = props; - const [open, setOpen] = React.useState(false); - const { handleUpload, listView } = props; - - const handleFileSelect = (event) => { - handleUpload?.(event); - setOpen(false); - }; - - return ( - - setOpen(true)}> - - - - setOpen(false)} - > - - Add new - - - - - - - - - Upload file - - - - - - {}} disabled> - - - - New folder - - - - - - ); -} - -ToolbarAddItem.propTypes = { - container: PropTypes.func, - handleUpload: PropTypes.func, - listView: PropTypes.bool.isRequired, -}; - -export { ToolbarAddItem }; diff --git a/docs/data/material/components/autocomplete/components/ToolbarAddItem.tsx b/docs/data/material/components/autocomplete/components/ToolbarAddItem.tsx deleted file mode 100644 index a3c43ffda857d5..00000000000000 --- a/docs/data/material/components/autocomplete/components/ToolbarAddItem.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import * as React from 'react'; -import AddIcon from '@mui/icons-material/Add'; -import CloudUploadIcon from '@mui/icons-material/CloudUpload'; -import NewFolderIcon from '@mui/icons-material/CreateNewFolder'; -import List from '@mui/material/List'; -import ListItem from '@mui/material/ListItem'; -import ListItemButton from '@mui/material/ListItemButton'; -import ListItemIcon from '@mui/material/ListItemIcon'; -import ListItemText from '@mui/material/ListItemText'; -import Typography from '@mui/material/Typography'; -import { ButtonProps } from '@mui/material/Button'; -import { ToolbarButton } from './ToolbarButton'; -import { Drawer, DrawerHeader, DrawerProps } from './Drawer'; - -const ListItemUploadButton = React.forwardRef( - function ListItemUploadButton(props, ref) { - const { children, ...other } = props; - return ( - - {children} - - ); - }, -); - -export interface ToolbarAddItemProps { - container: DrawerProps['container']; - listView: boolean; - handleUpload?: (event: React.ChangeEvent) => void; -} - -export function ToolbarAddItem(props: ToolbarAddItemProps) { - const { container } = props; - const [open, setOpen] = React.useState(false); - const { handleUpload, listView } = props; - - const handleFileSelect = (event: React.ChangeEvent) => { - handleUpload?.(event); - setOpen(false); - }; - - return ( - - setOpen(true)}> - - - - setOpen(false)} - > - - Add new - - - - - - - - - Upload file - - - - - - {}} disabled> - - - - New folder - - - - - - ); -} diff --git a/docs/data/material/components/autocomplete/components/ToolbarButton.js b/docs/data/material/components/autocomplete/components/ToolbarButton.js deleted file mode 100644 index 78113d989a16eb..00000000000000 --- a/docs/data/material/components/autocomplete/components/ToolbarButton.js +++ /dev/null @@ -1,18 +0,0 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; -import IconButton from '@mui/material/IconButton'; - -function ToolbarButton(props) { - const { className, children, ...other } = props; - return {children}; -} - -ToolbarButton.propTypes = { - /** - * The content of the component. - */ - children: PropTypes.node, - className: PropTypes.string, -}; - -export { ToolbarButton }; diff --git a/docs/data/material/components/autocomplete/components/ToolbarButton.tsx b/docs/data/material/components/autocomplete/components/ToolbarButton.tsx deleted file mode 100644 index 48b5dcf1ed3023..00000000000000 --- a/docs/data/material/components/autocomplete/components/ToolbarButton.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import * as React from 'react'; -import IconButton from '@mui/material/IconButton'; -import { ButtonProps } from '@mui/material/Button'; - -export function ToolbarButton(props: ButtonProps) { - const { className, children, ...other } = props; - return {children}; -} diff --git a/docs/data/material/components/autocomplete/components/ToolbarColumnsItem.js b/docs/data/material/components/autocomplete/components/ToolbarColumnsItem.js deleted file mode 100644 index fd2034d8b269f3..00000000000000 --- a/docs/data/material/components/autocomplete/components/ToolbarColumnsItem.js +++ /dev/null @@ -1,86 +0,0 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; -import { - GridColumnIcon, - useGridApiContext, - useGridSelector, - gridColumnDefinitionsSelector, - gridColumnVisibilityModelSelector, -} from '@mui/x-data-grid-premium'; -import CheckBoxIcon from '@mui/icons-material/CheckBox'; -import CheckBoxBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank'; -import Typography from '@mui/material/Typography'; -import List from '@mui/material/List'; -import ListItem from '@mui/material/ListItem'; -import ListItemButton from '@mui/material/ListItemButton'; -import ListItemIcon from '@mui/material/ListItemIcon'; -import ListItemText from '@mui/material/ListItemText'; -import { ToolbarButton } from './ToolbarButton'; -import { Drawer, DrawerHeader } from './Drawer'; - -function ToolbarColumnsItem(props) { - const { listView, container } = props; - const [open, setOpen] = React.useState(false); - const apiRef = useGridApiContext(); - const columns = useGridSelector(apiRef, gridColumnDefinitionsSelector); - const columnVisibilityModel = useGridSelector( - apiRef, - gridColumnVisibilityModelSelector, - ); - - const toggleFieldVisibility = (field) => { - apiRef.current.setColumnVisibility( - field, - columnVisibilityModel[field] === false, - ); - }; - - return ( - - setOpen(true)}> - - - - setOpen(false)} - > - - Fields - - - - {columns.map((column) => { - const isVisible = columnVisibilityModel[column.field] !== false; - return ( - - toggleFieldVisibility(column.field)} - disabled={column.hideable === false} - > - - {isVisible ? ( - - ) : ( - - )} - - {column.headerName || column.field} - - - ); - })} - - - - ); -} - -ToolbarColumnsItem.propTypes = { - container: PropTypes.func, - listView: PropTypes.bool.isRequired, -}; - -export { ToolbarColumnsItem }; diff --git a/docs/data/material/components/autocomplete/components/ToolbarColumnsItem.tsx b/docs/data/material/components/autocomplete/components/ToolbarColumnsItem.tsx deleted file mode 100644 index f4f55499d06edb..00000000000000 --- a/docs/data/material/components/autocomplete/components/ToolbarColumnsItem.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import * as React from 'react'; -import { - GridColumnIcon, - useGridApiContext, - useGridSelector, - gridColumnDefinitionsSelector, - gridColumnVisibilityModelSelector, -} from '@mui/x-data-grid-premium'; -import CheckBoxIcon from '@mui/icons-material/CheckBox'; -import CheckBoxBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank'; -import Typography from '@mui/material/Typography'; -import List from '@mui/material/List'; -import ListItem from '@mui/material/ListItem'; -import ListItemButton from '@mui/material/ListItemButton'; -import ListItemIcon from '@mui/material/ListItemIcon'; -import ListItemText from '@mui/material/ListItemText'; -import { ToolbarButton } from './ToolbarButton'; -import { Drawer, DrawerHeader, DrawerProps } from './Drawer'; - -interface ToolbarColumnsItemProps { - listView: boolean; - container: DrawerProps['container']; -} - -export function ToolbarColumnsItem(props: ToolbarColumnsItemProps) { - const { listView, container } = props; - const [open, setOpen] = React.useState(false); - const apiRef = useGridApiContext(); - const columns = useGridSelector(apiRef, gridColumnDefinitionsSelector); - const columnVisibilityModel = useGridSelector( - apiRef, - gridColumnVisibilityModelSelector, - ); - - const toggleFieldVisibility = (field: string) => { - apiRef.current.setColumnVisibility( - field, - columnVisibilityModel[field] === false, - ); - }; - - return ( - - setOpen(true)}> - - - - setOpen(false)} - > - - Fields - - - - {columns.map((column) => { - const isVisible = columnVisibilityModel[column.field] !== false; - return ( - - toggleFieldVisibility(column.field)} - disabled={column.hideable === false} - > - - {isVisible ? ( - - ) : ( - - )} - - {column.headerName || column.field} - - - ); - })} - - - - ); -} diff --git a/docs/data/material/components/autocomplete/components/ToolbarDensityItem.js b/docs/data/material/components/autocomplete/components/ToolbarDensityItem.js deleted file mode 100644 index 132acf81a76317..00000000000000 --- a/docs/data/material/components/autocomplete/components/ToolbarDensityItem.js +++ /dev/null @@ -1,95 +0,0 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; -import { - GridViewStreamIcon, - useGridApiContext, - useGridSelector, - gridDensitySelector, - GridCheckIcon, - GridViewHeadlineIcon, - GridTableRowsIcon, -} from '@mui/x-data-grid-premium'; -import List from '@mui/material/List'; -import ListItem from '@mui/material/ListItem'; -import ListItemButton from '@mui/material/ListItemButton'; -import ListItemText from '@mui/material/ListItemText'; -import ListItemIcon from '@mui/material/ListItemIcon'; -import Typography from '@mui/material/Typography'; -import { Drawer, DrawerHeader } from './Drawer'; -import { ToolbarButton } from './ToolbarButton'; - -const DENSITY_ICONS = { - compact: GridViewHeadlineIcon, - standard: GridTableRowsIcon, - comfortable: GridViewStreamIcon, -}; - -const DENSITY_OPTIONS = [ - { - label: 'Compact', - value: 'compact', - }, - { - label: 'Standard', - value: 'standard', - }, - { - label: 'Comfortable', - value: 'comfortable', - }, -]; - -function ToolbarDensityItem(props) { - const { listView, container } = props; - const [open, setOpen] = React.useState(false); - const apiRef = useGridApiContext(); - const density = useGridSelector(apiRef, gridDensitySelector); - - const handleDensityChange = (value) => { - apiRef.current.setDensity(value); - setOpen(false); - }; - - const Icon = DENSITY_ICONS[density]; - - return ( - - setOpen(true)}> - - - - setOpen(false)} - > - - Density - - - - {DENSITY_OPTIONS.map((option) => { - const isActive = density === option.value; - - return ( - - handleDensityChange(option.value)}> - {isActive ? : null} - {option.label} - - - ); - })} - - - - ); -} - -ToolbarDensityItem.propTypes = { - container: PropTypes.func, - listView: PropTypes.bool.isRequired, -}; - -export { ToolbarDensityItem }; diff --git a/docs/data/material/components/autocomplete/components/ToolbarDensityItem.tsx b/docs/data/material/components/autocomplete/components/ToolbarDensityItem.tsx deleted file mode 100644 index 8f9ce7a1846ed0..00000000000000 --- a/docs/data/material/components/autocomplete/components/ToolbarDensityItem.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import * as React from 'react'; -import { - GridViewStreamIcon, - useGridApiContext, - useGridSelector, - GridDensityOption, - gridDensitySelector, - GridCheckIcon, - GridDensity, - GridViewHeadlineIcon, - GridTableRowsIcon, -} from '@mui/x-data-grid-premium'; -import List from '@mui/material/List'; -import ListItem from '@mui/material/ListItem'; -import ListItemButton from '@mui/material/ListItemButton'; -import ListItemText from '@mui/material/ListItemText'; -import ListItemIcon from '@mui/material/ListItemIcon'; -import Typography from '@mui/material/Typography'; -import { Drawer, DrawerHeader, DrawerProps } from './Drawer'; -import { ToolbarButton } from './ToolbarButton'; - -const DENSITY_ICONS = { - compact: GridViewHeadlineIcon, - standard: GridTableRowsIcon, - comfortable: GridViewStreamIcon, -}; - -const DENSITY_OPTIONS: Omit[] = [ - { - label: 'Compact', - value: 'compact', - }, - { - label: 'Standard', - value: 'standard', - }, - { - label: 'Comfortable', - value: 'comfortable', - }, -]; - -interface ToolbarDensityItemProps { - listView: boolean; - container: DrawerProps['container']; -} - -export function ToolbarDensityItem(props: ToolbarDensityItemProps) { - const { listView, container } = props; - const [open, setOpen] = React.useState(false); - const apiRef = useGridApiContext(); - const density = useGridSelector(apiRef, gridDensitySelector); - - const handleDensityChange = (value: GridDensity) => { - apiRef.current.setDensity(value); - setOpen(false); - }; - - const Icon = DENSITY_ICONS[density]; - - return ( - - setOpen(true)}> - - - - setOpen(false)} - > - - Density - - - - {DENSITY_OPTIONS.map((option) => { - const isActive = density === option.value; - - return ( - - handleDensityChange(option.value)}> - {isActive ? : null} - {option.label} - - - ); - })} - - - - ); -} diff --git a/docs/data/material/components/autocomplete/components/ToolbarFilterItem.js b/docs/data/material/components/autocomplete/components/ToolbarFilterItem.js deleted file mode 100644 index 990eee997a6cc7..00000000000000 --- a/docs/data/material/components/autocomplete/components/ToolbarFilterItem.js +++ /dev/null @@ -1,225 +0,0 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; -import { - GridFilterListIcon, - useGridApiContext, - useGridSelector, - gridFilterActiveItemsSelector, - GridCheckIcon, -} from '@mui/x-data-grid-premium'; -import Badge from '@mui/material/Badge'; -import Typography from '@mui/material/Typography'; -import Divider from '@mui/material/Divider'; -import List from '@mui/material/List'; -import ListItem from '@mui/material/ListItem'; -import ListItemIcon from '@mui/material/ListItemIcon'; -import ListItemButton from '@mui/material/ListItemButton'; -import ListItemText from '@mui/material/ListItemText'; -import ListSubheader from '@mui/material/ListSubheader'; -import CheckBoxIcon from '@mui/icons-material/CheckBox'; -import CheckBoxBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank'; -import FilterAltOffIcon from '@mui/icons-material/FilterAltOff'; -import { Drawer, DrawerHeader } from './Drawer'; -import { ToolbarButton } from './ToolbarButton'; - -import { FILE_TYPES } from '../constants'; - -const DATE_MODIFIED_FILTERS = [ - { - label: 'All', - id: 'all', - }, - { - label: 'Today', - id: 'today', - operator: 'onOrAfter', - value: new Date(new Date().setHours(0, 0, 0, 0)).toISOString(), - }, - { - label: 'Last week', - id: 'last-week', - operator: 'onOrAfter', - value: new Date( - new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).setHours(0, 0, 0, 0), - ).toISOString(), - }, - { - label: 'Last month', - id: 'last-month', - operator: 'onOrAfter', - value: new Date( - new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).setHours(0, 0, 0, 0), - ).toISOString(), - }, - { - label: 'Last 3 months', - id: 'last-3-months', - operator: 'onOrAfter', - value: new Date( - new Date(Date.now() - 3 * 30 * 24 * 60 * 60 * 1000).setHours(0, 0, 0, 0), - ).toISOString(), - }, -]; - -function ToolbarFilterItem(props) { - const { listView, container } = props; - const [open, setOpen] = React.useState(false); - const apiRef = useGridApiContext(); - const activeFilters = useGridSelector(apiRef, gridFilterActiveItemsSelector); - const currentFileTypeFilter = - activeFilters.filter((filter) => filter.field === 'type')?.[0]?.value ?? []; - const currentDateModifiedFilter = activeFilters.find( - (filter) => filter.field === 'updatedAt', - ); - - const applyDateModifiedFilter = (filterItem) => { - if (currentDateModifiedFilter) { - apiRef.current.deleteFilterItem(currentDateModifiedFilter); - } - - apiRef.current.upsertFilterItem({ - field: 'updatedAt', - ...filterItem, - }); - }; - - const resetDateModifiedFilter = () => { - if (currentDateModifiedFilter) { - apiRef.current.deleteFilterItem(currentDateModifiedFilter); - } - }; - - const applyFileTypeFilter = (fileType, enable) => { - apiRef.current.upsertFilterItem({ - id: 'file-type', - field: 'type', - operator: 'isAnyOf', - value: enable - ? [...currentFileTypeFilter, fileType] - : currentFileTypeFilter.filter((type) => type !== fileType), - }); - }; - - const clearFilters = () => { - apiRef.current.setFilterModel({ - items: [], - }); - }; - - return ( - - setOpen(true)}> - - - - - - setOpen(false)} - > - - Filters - - - - Date modified - - } - > - {DATE_MODIFIED_FILTERS.map((option) => { - const isActive = - option.id === 'all' - ? !currentDateModifiedFilter - : activeFilters.some((filter) => filter.id === option.id); - - return ( - - - option.id === 'all' - ? resetDateModifiedFilter() - : applyDateModifiedFilter({ - id: option.id, - operator: option.operator, - value: option.value, - }) - } - > - {isActive ? : null} - {option.label} - - - ); - })} - - - - - File types - - } - > - {FILE_TYPES.map((type) => { - const isActive = currentFileTypeFilter.includes(type); - - return ( - - applyFileTypeFilter(type, !isActive)}> - - {isActive ? ( - - ) : ( - - )} - - {type} - - - ); - })} - - - - - - - - - - Clear filters - - - - - - ); -} - -ToolbarFilterItem.propTypes = { - container: PropTypes.func, - listView: PropTypes.bool.isRequired, -}; - -export { ToolbarFilterItem }; diff --git a/docs/data/material/components/autocomplete/components/ToolbarFilterItem.tsx b/docs/data/material/components/autocomplete/components/ToolbarFilterItem.tsx deleted file mode 100644 index 2bb3040df9cd8d..00000000000000 --- a/docs/data/material/components/autocomplete/components/ToolbarFilterItem.tsx +++ /dev/null @@ -1,225 +0,0 @@ -import * as React from 'react'; -import { - GridFilterListIcon, - useGridApiContext, - useGridSelector, - gridFilterActiveItemsSelector, - GridCheckIcon, - GridFilterItem, -} from '@mui/x-data-grid-premium'; -import Badge from '@mui/material/Badge'; -import Typography from '@mui/material/Typography'; -import Divider from '@mui/material/Divider'; -import List from '@mui/material/List'; -import ListItem from '@mui/material/ListItem'; -import ListItemIcon from '@mui/material/ListItemIcon'; -import ListItemButton from '@mui/material/ListItemButton'; -import ListItemText from '@mui/material/ListItemText'; -import ListSubheader from '@mui/material/ListSubheader'; -import CheckBoxIcon from '@mui/icons-material/CheckBox'; -import CheckBoxBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank'; -import FilterAltOffIcon from '@mui/icons-material/FilterAltOff'; -import { Drawer, DrawerHeader, DrawerProps } from './Drawer'; -import { ToolbarButton } from './ToolbarButton'; -import { FileType } from '../types'; -import { FILE_TYPES } from '../constants'; - -const DATE_MODIFIED_FILTERS = [ - { - label: 'All', - id: 'all', - }, - { - label: 'Today', - id: 'today', - operator: 'onOrAfter', - value: new Date(new Date().setHours(0, 0, 0, 0)).toISOString(), - }, - { - label: 'Last week', - id: 'last-week', - operator: 'onOrAfter', - value: new Date( - new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).setHours(0, 0, 0, 0), - ).toISOString(), - }, - { - label: 'Last month', - id: 'last-month', - operator: 'onOrAfter', - value: new Date( - new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).setHours(0, 0, 0, 0), - ).toISOString(), - }, - { - label: 'Last 3 months', - id: 'last-3-months', - operator: 'onOrAfter', - value: new Date( - new Date(Date.now() - 3 * 30 * 24 * 60 * 60 * 1000).setHours(0, 0, 0, 0), - ).toISOString(), - }, -]; - -interface ToolbarFilterItemProps { - listView: boolean; - container: DrawerProps['container']; -} - -export function ToolbarFilterItem(props: ToolbarFilterItemProps) { - const { listView, container } = props; - const [open, setOpen] = React.useState(false); - const apiRef = useGridApiContext(); - const activeFilters = useGridSelector(apiRef, gridFilterActiveItemsSelector); - const currentFileTypeFilter = - activeFilters.filter((filter) => filter.field === 'type')?.[0]?.value ?? []; - const currentDateModifiedFilter = activeFilters.find( - (filter) => filter.field === 'updatedAt', - ); - - const applyDateModifiedFilter = (filterItem: Omit) => { - if (currentDateModifiedFilter) { - apiRef.current.deleteFilterItem(currentDateModifiedFilter); - } - - apiRef.current.upsertFilterItem({ - field: 'updatedAt', - ...filterItem, - }); - }; - - const resetDateModifiedFilter = () => { - if (currentDateModifiedFilter) { - apiRef.current.deleteFilterItem(currentDateModifiedFilter); - } - }; - - const applyFileTypeFilter = (fileType: FileType, enable: boolean) => { - apiRef.current.upsertFilterItem({ - id: 'file-type', - field: 'type', - operator: 'isAnyOf', - value: enable - ? [...currentFileTypeFilter, fileType] - : currentFileTypeFilter.filter((type: string) => type !== fileType), - }); - }; - - const clearFilters = () => { - apiRef.current.setFilterModel({ - items: [], - }); - }; - - return ( - - setOpen(true)}> - - - - - - setOpen(false)} - > - - Filters - - - - Date modified - - } - > - {DATE_MODIFIED_FILTERS.map((option) => { - const isActive = - option.id === 'all' - ? !currentDateModifiedFilter - : activeFilters.some((filter) => filter.id === option.id); - - return ( - - - option.id === 'all' - ? resetDateModifiedFilter() - : applyDateModifiedFilter({ - id: option.id, - operator: option.operator!, - value: option.value, - }) - } - > - {isActive ? : null} - {option.label} - - - ); - })} - - - - - - File types - - } - > - {FILE_TYPES.map((type) => { - const isActive = currentFileTypeFilter.includes(type); - - return ( - - applyFileTypeFilter(type, !isActive)}> - - {isActive ? ( - - ) : ( - - )} - - {type} - - - ); - })} - - - - - - - - - - - Clear filters - - - - - - ); -} diff --git a/docs/data/material/components/autocomplete/components/ToolbarSortItem.js b/docs/data/material/components/autocomplete/components/ToolbarSortItem.js deleted file mode 100644 index c34894a3aaf49c..00000000000000 --- a/docs/data/material/components/autocomplete/components/ToolbarSortItem.js +++ /dev/null @@ -1,101 +0,0 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; -import { - useGridApiContext, - GridArrowUpwardIcon, - GridArrowDownwardIcon, - useGridSelector, - gridSortModelSelector, - gridColumnDefinitionsSelector, -} from '@mui/x-data-grid-premium'; -import SwapVertIcon from '@mui/icons-material/SwapVert'; -import List from '@mui/material/List'; -import ListItem from '@mui/material/ListItem'; -import ListItemButton from '@mui/material/ListItemButton'; -import ListItemText from '@mui/material/ListItemText'; -import ListItemIcon from '@mui/material/ListItemIcon'; -import Typography from '@mui/material/Typography'; -import Badge from '@mui/material/Badge'; -import { Drawer, DrawerHeader } from './Drawer'; -import { ToolbarButton } from './ToolbarButton'; - -function ToolbarSortItem(props) { - const { listView, container } = props; - const [open, setOpen] = React.useState(false); - const apiRef = useGridApiContext(); - const fields = useGridSelector(apiRef, gridColumnDefinitionsSelector); - const sortModel = useGridSelector(apiRef, gridSortModelSelector); - const sortableFields = fields.filter((field) => field.sortable); - const sortCount = sortModel.length; - - const handleSortChange = (field, sort) => { - apiRef.current.sortColumn(field, sort, true); - }; - - return ( - - setOpen(true)}> - - - - - - setOpen(false)} - > - - Sort by - - - - {sortableFields.map((field) => { - const fieldIndexInSortModel = sortModel.findIndex( - (sort) => sort.field === field.field, - ); - const fieldInSortModel = sortModel[fieldIndexInSortModel]; - let nextSort = 'asc'; - - if (fieldInSortModel) { - nextSort = fieldInSortModel.sort === 'asc' ? 'desc' : null; - } - - return ( - - handleSortChange(field.field, nextSort)} - > - - {fieldInSortModel && ( - 1 ? fieldIndexInSortModel + 1 : null - } - > - {fieldInSortModel.sort === 'asc' ? ( - - ) : ( - - )} - - )} - - {field.headerName} - - - ); - })} - - - - ); -} - -ToolbarSortItem.propTypes = { - container: PropTypes.func, - listView: PropTypes.bool.isRequired, -}; - -export { ToolbarSortItem }; diff --git a/docs/data/material/components/autocomplete/components/ToolbarSortItem.tsx b/docs/data/material/components/autocomplete/components/ToolbarSortItem.tsx deleted file mode 100644 index 4c3633f6ec3d64..00000000000000 --- a/docs/data/material/components/autocomplete/components/ToolbarSortItem.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import * as React from 'react'; -import { - useGridApiContext, - GridArrowUpwardIcon, - GridArrowDownwardIcon, - useGridSelector, - gridSortModelSelector, - gridColumnDefinitionsSelector, - GridSortDirection, -} from '@mui/x-data-grid-premium'; -import SwapVertIcon from '@mui/icons-material/SwapVert'; -import List from '@mui/material/List'; -import ListItem from '@mui/material/ListItem'; -import ListItemButton from '@mui/material/ListItemButton'; -import ListItemText from '@mui/material/ListItemText'; -import ListItemIcon from '@mui/material/ListItemIcon'; -import Typography from '@mui/material/Typography'; -import Badge from '@mui/material/Badge'; -import { Drawer, DrawerHeader, DrawerProps } from './Drawer'; -import { ToolbarButton } from './ToolbarButton'; - -interface ToolbarSortItemProps { - listView: boolean; - container: DrawerProps['container']; -} - -export function ToolbarSortItem(props: ToolbarSortItemProps) { - const { listView, container } = props; - const [open, setOpen] = React.useState(false); - const apiRef = useGridApiContext(); - const fields = useGridSelector(apiRef, gridColumnDefinitionsSelector); - const sortModel = useGridSelector(apiRef, gridSortModelSelector); - const sortableFields = fields.filter((field) => field.sortable); - const sortCount = sortModel.length; - - const handleSortChange = (field: string, sort: GridSortDirection) => { - apiRef.current.sortColumn(field, sort, true); - }; - - return ( - - setOpen(true)}> - - - - - - setOpen(false)} - > - - Sort by - - - - {sortableFields.map((field) => { - const fieldIndexInSortModel = sortModel.findIndex( - (sort) => sort.field === field.field, - ); - const fieldInSortModel = sortModel[fieldIndexInSortModel]; - let nextSort: GridSortDirection = 'asc'; - - if (fieldInSortModel) { - nextSort = fieldInSortModel.sort === 'asc' ? 'desc' : null; - } - - return ( - - handleSortChange(field.field, nextSort)} - > - - {fieldInSortModel && ( - 1 ? fieldIndexInSortModel + 1 : null - } - > - {fieldInSortModel.sort === 'asc' ? ( - - ) : ( - - )} - - )} - - {field.headerName} - - - ); - })} - - - - ); -} diff --git a/docs/data/material/components/autocomplete/constants.js b/docs/data/material/components/autocomplete/constants.js deleted file mode 100644 index 367df998d63747..00000000000000 --- a/docs/data/material/components/autocomplete/constants.js +++ /dev/null @@ -1,15 +0,0 @@ -export const FILE_TYPES = [ - 'pdf', - 'docx', - 'txt', - 'mp4', - 'mov', - 'webm', - 'jpg', - 'jpeg', - 'png', - 'gif', - 'tiff', - 'webp', - 'zip', -]; diff --git a/docs/data/material/components/autocomplete/constants.ts b/docs/data/material/components/autocomplete/constants.ts deleted file mode 100644 index ee67fc4fb92c0f..00000000000000 --- a/docs/data/material/components/autocomplete/constants.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { FileType } from './types'; - -export const FILE_TYPES: FileType[] = [ - 'pdf', - 'docx', - 'txt', - 'mp4', - 'mov', - 'webm', - 'jpg', - 'jpeg', - 'png', - 'gif', - 'tiff', - 'webp', - 'zip', -]; diff --git a/docs/data/material/components/autocomplete/data.js b/docs/data/material/components/autocomplete/data.js deleted file mode 100644 index 39537f00c1f530..00000000000000 --- a/docs/data/material/components/autocomplete/data.js +++ /dev/null @@ -1,202 +0,0 @@ -import { randomId } from '@mui/x-data-grid-generator'; - -export const INITIAL_ROWS = [ - { - id: randomId(), - type: 'zip', - name: 'archive.zip', - description: 'Compressed archive of project files', - size: 128_313_213, - createdBy: 'Kenan Yusuf', - createdAt: new Date('2023-09-15T08:30:00').toISOString(), - updatedAt: new Date('2023-09-15T08:30:00').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'docx', - name: 'invoice-322.docx', - description: 'Invoice document for client 322', - size: 1_694_986, - createdBy: 'José Freitas', - createdAt: new Date('2024-01-18T11:30:00').toISOString(), - updatedAt: new Date().toISOString(), // Today - state: 'uploaded', - }, - { - id: randomId(), - type: 'png', - name: 'screenshot_2024-02-14_12-34-56.png', - description: 'Screenshot of application interface', - size: 522_078, - createdBy: 'José Freitas', - createdAt: new Date('2024-02-14T12:35:16').toISOString(), - updatedAt: new Date(Date.now() - 5 * 24 * 60 * 60 * 1000).toISOString(), // Last week - state: 'uploaded', - }, - { - id: randomId(), - type: 'mp4', - name: 'strategy-meeting.mp4', - description: 'Recording of the strategy planning meeting', - size: 2_442_044, - createdBy: 'José Freitas', - createdAt: new Date('2023-12-05T15:40:30').toISOString(), - updatedAt: new Date(Date.now() - 20 * 24 * 60 * 60 * 1000).toISOString(), // Last month - state: 'uploaded', - }, - { - id: randomId(), - type: 'docx', - name: 'project-proposal.docx', - description: 'Detailed project proposal document', - size: 3_567_890, - createdBy: 'Olivier Tassinari', - createdAt: new Date('2024-03-01T09:15:00').toISOString(), - updatedAt: new Date('2024-03-02T14:30:45').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'png', - name: 'logo-design-final.png', - description: 'Final version of the company logo design', - size: 1_234_567, - createdBy: 'Kenan Yusuf', - createdAt: new Date('2024-02-28T16:20:00').toISOString(), - updatedAt: new Date('2024-02-28T16:20:00').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'mp4', - name: 'product-demo.mp4', - description: 'Video demonstration of the new product features', - size: 15_789_012, - createdBy: 'Olivier Tassinari', - createdAt: new Date('2024-02-25T11:45:00').toISOString(), - updatedAt: new Date(Date.now() - 60 * 24 * 60 * 60 * 1000).toISOString(), // Last 3 months - state: 'uploaded', - }, - { - id: randomId(), - type: 'zip', - name: 'project-assets.zip', - description: 'Compressed folder containing all project assets', - size: 87_654_321, - createdBy: 'José Freitas', - createdAt: new Date('2024-03-03T13:00:00').toISOString(), - updatedAt: new Date('2024-03-03T13:00:00').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'docx', - name: 'meeting-minutes-2024-03-10.docx', - description: 'Minutes from the team meeting on March 10, 2024', - size: 567_890, - createdBy: 'Kenan Yusuf', - createdAt: new Date('2024-03-10T14:00:00').toISOString(), - updatedAt: new Date('2024-03-10T16:30:00').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'png', - name: 'ui-mockup-v2.png', - description: 'Updated user interface mockup', - size: 3_456_789, - createdBy: 'Olivier Tassinari', - createdAt: new Date('2024-03-05T10:20:00').toISOString(), - updatedAt: new Date('2024-03-05T10:20:00').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'mp4', - name: 'user-feedback-session.mp4', - description: 'Recording of user feedback session', - size: 234_567_890, - createdBy: 'José Freitas', - createdAt: new Date('2024-03-08T13:45:00').toISOString(), - updatedAt: new Date('2024-03-08T15:30:00').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'zip', - name: 'legacy-codebase.zip', - description: 'Archive of the legacy project codebase', - size: 567_890_123, - createdBy: 'Kenan Yusuf', - createdAt: new Date('2024-02-20T09:00:00').toISOString(), - updatedAt: new Date('2024-02-20T09:00:00').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'docx', - name: 'q1-2024-report.docx', - description: 'Quarterly report for Q1 2024', - size: 4_567_890, - createdBy: 'Olivier Tassinari', - createdAt: new Date('2024-03-31T23:59:59').toISOString(), - updatedAt: new Date('2024-04-01T10:15:00').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'png', - name: 'data-visualization.png', - description: 'Chart showing project progress', - size: 789_012, - createdBy: 'José Freitas', - createdAt: new Date('2024-03-15T11:30:00').toISOString(), - updatedAt: new Date('2024-03-15T11:30:00').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'mp4', - name: 'code-review-session.mp4', - description: 'Recording of code review meeting', - size: 345_678_901, - createdBy: 'Kenan Yusuf', - createdAt: new Date('2024-03-20T14:00:00').toISOString(), - updatedAt: new Date('2024-03-20T16:45:00').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'zip', - name: 'design-assets-v3.zip', - description: 'Compressed folder of updated design assets', - size: 98_765_432, - createdBy: 'Olivier Tassinari', - createdAt: new Date('2024-03-25T09:30:00').toISOString(), - updatedAt: new Date('2024-03-25T09:30:00').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'docx', - name: 'api-documentation.docx', - description: 'Comprehensive API documentation', - size: 2_345_678, - createdBy: 'José Freitas', - createdAt: new Date('2024-03-28T16:20:00').toISOString(), - updatedAt: new Date('2024-03-29T11:45:00').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'png', - name: 'error-screenshot.png', - description: 'Screenshot of error message for debugging', - size: 345_678, - createdBy: 'Kenan Yusuf', - createdAt: new Date('2024-03-30T08:15:00').toISOString(), - updatedAt: new Date('2024-03-30T08:15:00').toISOString(), - state: 'uploaded', - }, -]; diff --git a/docs/data/material/components/autocomplete/data.ts b/docs/data/material/components/autocomplete/data.ts deleted file mode 100644 index 3e54d301d2c7fd..00000000000000 --- a/docs/data/material/components/autocomplete/data.ts +++ /dev/null @@ -1,204 +0,0 @@ -import { randomId } from '@mui/x-data-grid-generator'; -import { GridRowModel } from '@mui/x-data-grid-premium'; -import { RowModel } from './types'; - -export const INITIAL_ROWS: GridRowModel[] = [ - { - id: randomId(), - type: 'zip', - name: 'archive.zip', - description: 'Compressed archive of project files', - size: 128_313_213, - createdBy: 'Kenan Yusuf', - createdAt: new Date('2023-09-15T08:30:00').toISOString(), - updatedAt: new Date('2023-09-15T08:30:00').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'docx', - name: 'invoice-322.docx', - description: 'Invoice document for client 322', - size: 1_694_986, - createdBy: 'José Freitas', - createdAt: new Date('2024-01-18T11:30:00').toISOString(), - updatedAt: new Date().toISOString(), // Today - state: 'uploaded', - }, - { - id: randomId(), - type: 'png', - name: 'screenshot_2024-02-14_12-34-56.png', - description: 'Screenshot of application interface', - size: 522_078, - createdBy: 'José Freitas', - createdAt: new Date('2024-02-14T12:35:16').toISOString(), - updatedAt: new Date(Date.now() - 5 * 24 * 60 * 60 * 1000).toISOString(), // Last week - state: 'uploaded', - }, - { - id: randomId(), - type: 'mp4', - name: 'strategy-meeting.mp4', - description: 'Recording of the strategy planning meeting', - size: 2_442_044, - createdBy: 'José Freitas', - createdAt: new Date('2023-12-05T15:40:30').toISOString(), - updatedAt: new Date(Date.now() - 20 * 24 * 60 * 60 * 1000).toISOString(), // Last month - state: 'uploaded', - }, - { - id: randomId(), - type: 'docx', - name: 'project-proposal.docx', - description: 'Detailed project proposal document', - size: 3_567_890, - createdBy: 'Olivier Tassinari', - createdAt: new Date('2024-03-01T09:15:00').toISOString(), - updatedAt: new Date('2024-03-02T14:30:45').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'png', - name: 'logo-design-final.png', - description: 'Final version of the company logo design', - size: 1_234_567, - createdBy: 'Kenan Yusuf', - createdAt: new Date('2024-02-28T16:20:00').toISOString(), - updatedAt: new Date('2024-02-28T16:20:00').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'mp4', - name: 'product-demo.mp4', - description: 'Video demonstration of the new product features', - size: 15_789_012, - createdBy: 'Olivier Tassinari', - createdAt: new Date('2024-02-25T11:45:00').toISOString(), - updatedAt: new Date(Date.now() - 60 * 24 * 60 * 60 * 1000).toISOString(), // Last 3 months - state: 'uploaded', - }, - { - id: randomId(), - type: 'zip', - name: 'project-assets.zip', - description: 'Compressed folder containing all project assets', - size: 87_654_321, - createdBy: 'José Freitas', - createdAt: new Date('2024-03-03T13:00:00').toISOString(), - updatedAt: new Date('2024-03-03T13:00:00').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'docx', - name: 'meeting-minutes-2024-03-10.docx', - description: 'Minutes from the team meeting on March 10, 2024', - size: 567_890, - createdBy: 'Kenan Yusuf', - createdAt: new Date('2024-03-10T14:00:00').toISOString(), - updatedAt: new Date('2024-03-10T16:30:00').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'png', - name: 'ui-mockup-v2.png', - description: 'Updated user interface mockup', - size: 3_456_789, - createdBy: 'Olivier Tassinari', - createdAt: new Date('2024-03-05T10:20:00').toISOString(), - updatedAt: new Date('2024-03-05T10:20:00').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'mp4', - name: 'user-feedback-session.mp4', - description: 'Recording of user feedback session', - size: 234_567_890, - createdBy: 'José Freitas', - createdAt: new Date('2024-03-08T13:45:00').toISOString(), - updatedAt: new Date('2024-03-08T15:30:00').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'zip', - name: 'legacy-codebase.zip', - description: 'Archive of the legacy project codebase', - size: 567_890_123, - createdBy: 'Kenan Yusuf', - createdAt: new Date('2024-02-20T09:00:00').toISOString(), - updatedAt: new Date('2024-02-20T09:00:00').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'docx', - name: 'q1-2024-report.docx', - description: 'Quarterly report for Q1 2024', - size: 4_567_890, - createdBy: 'Olivier Tassinari', - createdAt: new Date('2024-03-31T23:59:59').toISOString(), - updatedAt: new Date('2024-04-01T10:15:00').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'png', - name: 'data-visualization.png', - description: 'Chart showing project progress', - size: 789_012, - createdBy: 'José Freitas', - createdAt: new Date('2024-03-15T11:30:00').toISOString(), - updatedAt: new Date('2024-03-15T11:30:00').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'mp4', - name: 'code-review-session.mp4', - description: 'Recording of code review meeting', - size: 345_678_901, - createdBy: 'Kenan Yusuf', - createdAt: new Date('2024-03-20T14:00:00').toISOString(), - updatedAt: new Date('2024-03-20T16:45:00').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'zip', - name: 'design-assets-v3.zip', - description: 'Compressed folder of updated design assets', - size: 98_765_432, - createdBy: 'Olivier Tassinari', - createdAt: new Date('2024-03-25T09:30:00').toISOString(), - updatedAt: new Date('2024-03-25T09:30:00').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'docx', - name: 'api-documentation.docx', - description: 'Comprehensive API documentation', - size: 2_345_678, - createdBy: 'José Freitas', - createdAt: new Date('2024-03-28T16:20:00').toISOString(), - updatedAt: new Date('2024-03-29T11:45:00').toISOString(), - state: 'uploaded', - }, - { - id: randomId(), - type: 'png', - name: 'error-screenshot.png', - description: 'Screenshot of error message for debugging', - size: 345_678, - createdBy: 'Kenan Yusuf', - createdAt: new Date('2024-03-30T08:15:00').toISOString(), - updatedAt: new Date('2024-03-30T08:15:00').toISOString(), - state: 'uploaded', - }, -]; diff --git a/docs/data/material/components/autocomplete/types.ts b/docs/data/material/components/autocomplete/types.ts deleted file mode 100644 index fd0975f3a0b952..00000000000000 --- a/docs/data/material/components/autocomplete/types.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { GridRowId } from '@mui/x-data-grid-premium'; - -export type FileType = - | 'pdf' - | 'docx' - | 'txt' - | 'mp4' - | 'mov' - | 'webm' - | 'jpg' - | 'jpeg' - | 'png' - | 'gif' - | 'tiff' - | 'webp' - | 'zip'; - -export type FileState = 'uploaded' | 'pending'; - -export type RowModel = { - id: GridRowId; - type: FileType; - name: string; - description: string; - size: number; - createdBy: string; - createdAt: string; - updatedAt: string; - state: FileState; -}; diff --git a/docs/data/material/components/autocomplete/utils.js b/docs/data/material/components/autocomplete/utils.js deleted file mode 100644 index 8e75f8418c0ff4..00000000000000 --- a/docs/data/material/components/autocomplete/utils.js +++ /dev/null @@ -1,56 +0,0 @@ -export function formatDate(value) { - if (!value) { - return '—'; - } - const date = new Date(value); - const formatter = new Intl.DateTimeFormat('en-US', { - month: 'short', - day: '2-digit', - year: 'numeric', - hour: '2-digit', - minute: '2-digit', - }); - return formatter.format(date); -} - -export function formatSize(size) { - const units = ['B', 'KB', 'MB', 'GB', 'TB']; - let unitIndex = 0; - let formattedSize = size; - - while (formattedSize >= 1024 && unitIndex < units.length - 1) { - formattedSize /= 1024; - unitIndex += 1; - } - - return `${formattedSize.toFixed(2)} ${units[unitIndex]}`; -} - -export function stringToColor(string) { - let hash = 0; - let i; - - /* eslint-disable no-bitwise */ - for (i = 0; i < string.length; i += 1) { - hash = string.charCodeAt(i) + ((hash << 5) - hash); - } - - let color = '#'; - - for (i = 0; i < 3; i += 1) { - const value = (hash >> (i * 8)) & 0xff; - color += `00${value.toString(16)}`.slice(-2); - } - /* eslint-enable no-bitwise */ - - return color; -} - -export function stringAvatar(name) { - return { - sx: { - bgcolor: stringToColor(name), - }, - children: `${name.split(' ')[0][0]}${name.split(' ')[1][0]}`, - }; -} diff --git a/docs/data/material/components/autocomplete/utils.ts b/docs/data/material/components/autocomplete/utils.ts deleted file mode 100644 index 08c93be0d27c40..00000000000000 --- a/docs/data/material/components/autocomplete/utils.ts +++ /dev/null @@ -1,56 +0,0 @@ -export function formatDate(value: string | null) { - if (!value) { - return '—'; - } - const date = new Date(value); - const formatter = new Intl.DateTimeFormat('en-US', { - month: 'short', - day: '2-digit', - year: 'numeric', - hour: '2-digit', - minute: '2-digit', - }); - return formatter.format(date); -} - -export function formatSize(size: number) { - const units = ['B', 'KB', 'MB', 'GB', 'TB']; - let unitIndex = 0; - let formattedSize = size; - - while (formattedSize >= 1024 && unitIndex < units.length - 1) { - formattedSize /= 1024; - unitIndex += 1; - } - - return `${formattedSize.toFixed(2)} ${units[unitIndex]}`; -} - -export function stringToColor(string: string) { - let hash = 0; - let i: number; - - /* eslint-disable no-bitwise */ - for (i = 0; i < string.length; i += 1) { - hash = string.charCodeAt(i) + ((hash << 5) - hash); - } - - let color = '#'; - - for (i = 0; i < 3; i += 1) { - const value = (hash >> (i * 8)) & 0xff; - color += `00${value.toString(16)}`.slice(-2); - } - /* eslint-enable no-bitwise */ - - return color; -} - -export function stringAvatar(name: string) { - return { - sx: { - bgcolor: stringToColor(name), - }, - children: `${name.split(' ')[0][0]}${name.split(' ')[1][0]}`, - }; -} From 0463a8a7ac871db214b82061919f4bfae9e81d9c Mon Sep 17 00:00:00 2001 From: mnajdova Date: Fri, 25 Oct 2024 11:34:10 +0200 Subject: [PATCH 13/17] lint issue --- docs/src/modules/sandbox/FlattenRelativeImports.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/modules/sandbox/FlattenRelativeImports.ts b/docs/src/modules/sandbox/FlattenRelativeImports.ts index 521e43ba6dbc4c..44bfdc247e6e6f 100644 --- a/docs/src/modules/sandbox/FlattenRelativeImports.ts +++ b/docs/src/modules/sandbox/FlattenRelativeImports.ts @@ -1,3 +1,3 @@ export default function flattenRelativeImports(rawCode: string) { - return rawCode.replace(/from (['"])\..*[\/]/g, `from $1./`); + return rawCode.replace(/from (['"])\..*\//g, `from $1./`); } From 84a5210506744d249a5f07f6b598818e5f9d6d1c Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Wed, 30 Oct 2024 08:09:02 +0100 Subject: [PATCH 14/17] Update packages/markdown/loader.js Co-authored-by: Bharat Kashyap Signed-off-by: Marija Najdova --- packages/markdown/loader.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/markdown/loader.js b/packages/markdown/loader.js index c96cde3bd6274b..dc80f214dca576 100644 --- a/packages/markdown/loader.js +++ b/packages/markdown/loader.js @@ -148,6 +148,7 @@ module.exports = async function demoLoader() { * @param {*} moduleFilepath * @param {*} variant * @param {*} importModuleID + * @returns {string} The name of the imported module along with a resolved extension if not provided * @example detectRelativeImports('ComboBox.js', '', JS', './top100Films') => relativeModules.set('ComboBox.js', new Map([['./top100Films.js', ['JS']]])) */ function detectRelativeImports(demoName, moduleFilepath, variant, importModuleID) { From 87afe6c10d85d9fd98ec1db71722132ba7effc36 Mon Sep 17 00:00:00 2001 From: mnajdova Date: Wed, 30 Oct 2024 08:14:31 +0100 Subject: [PATCH 15/17] move function outside of loop --- packages/markdown/loader.js | 45 ++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/packages/markdown/loader.js b/packages/markdown/loader.js index dc80f214dca576..32559615ad9ab7 100644 --- a/packages/markdown/loader.js +++ b/packages/markdown/loader.js @@ -202,6 +202,26 @@ module.exports = async function demoLoader() { return relativeModuleFilename; } + /** + * Inserts the moduleData into the relativeModules object + * @param string demoName + * @param {*} moduleData + * @param string variant + * @example updateRelativeModules(demoName, {module: 'constants.js', raw: ... }, 'JS') => demos[demoName].relativeModules[variant].push(moduleData) + */ + function updateRelativeModules(demoName, moduleData, variant) { + if (demos[demoName].relativeModules[variant]) { + // Avoid duplicates + if ( + !demos[demoName].relativeModules[variant].some((elem) => elem.module === moduleData.module) + ) { + demos[demoName].relativeModules[variant].push(moduleData); + } + } else { + demos[demoName].relativeModules[variant] = [moduleData]; + } + } + await Promise.all( demoNames.map(async (demoName) => { const multipleDemoVersionsUsed = !demoName.endsWith('.js'); @@ -421,27 +441,6 @@ module.exports = async function demoLoader() { // TS version of the demo doesn't exist. This is fine. } - /** - * Inserts the moduleData into the relativeModules object - * @param {*} moduleData - * @param {*} variant - * @example updateRelativeModules({module: 'constants.js', raw: ... }, 'JS') => demos[demoName].relativeModules[variant].push(moduleData) - */ - function updateRelativeModules(moduleData, variant) { - if (demos[demoName].relativeModules[variant]) { - // Avoid duplicates - if ( - !demos[demoName].relativeModules[variant].some( - (elem) => elem.module === moduleData.module, - ) - ) { - demos[demoName].relativeModules[variant].push(moduleData); - } - } else { - demos[demoName].relativeModules[variant] = [moduleData]; - } - } - /* Map over relative import module IDs and resolve them * while grouping by demo variant * From: @@ -507,7 +506,7 @@ module.exports = async function demoLoader() { if (!addedModulesRelativeToModulePath.has(relativeModuleFilePath)) { const moduleData = { module: relativeModuleID, raw }; - updateRelativeModules(moduleData, variant); + updateRelativeModules(demoName, moduleData, variant); addedModulesRelativeToModulePath.add(relativeModuleFilePath); } } @@ -551,7 +550,7 @@ module.exports = async function demoLoader() { module: `.${entryModuleFilePath.replace(modulePathDirectory, '')}`, raw: rawEntry, }; - updateRelativeModules(moduleData, variant); + updateRelativeModules(demoName, moduleData, variant); addedModulesRelativeToModulePath.add(entryModuleFilePath); } } From 87dc3fd35d32d58ccbfc51bcd2ae2350fb797100 Mon Sep 17 00:00:00 2001 From: mnajdova Date: Wed, 30 Oct 2024 08:18:49 +0100 Subject: [PATCH 16/17] remove unnecessary conditions --- packages/markdown/loader.js | 38 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/packages/markdown/loader.js b/packages/markdown/loader.js index 32559615ad9ab7..22653ae21d2950 100644 --- a/packages/markdown/loader.js +++ b/packages/markdown/loader.js @@ -486,30 +486,26 @@ module.exports = async function demoLoader() { const importedProcessedModuleIDs = new Set(); const importedProcessedModulesIDsParents = new Map(); // Find the relative paths in the relative module - if (relativeModuleID.startsWith('.')) { - extractImports(raw).forEach((importModuleID) => { - // detect relative import - const importModuleIdWithExtension = detectRelativeImports( - importModuleID, + extractImports(raw).forEach((importModuleID) => { + // detect relative import + const importModuleIdWithExtension = detectRelativeImports( + importModuleID, + relativeModuleFilePath, + variant, + importModuleID, + ); + if (importModuleID.startsWith('.')) { + importedProcessedModuleIDs.add(importModuleIdWithExtension); + importedProcessedModulesIDsParents.set( + importModuleIdWithExtension, relativeModuleFilePath, - variant, - importModuleID, ); - if (importModuleID.startsWith('.')) { - importedProcessedModuleIDs.add(importModuleIdWithExtension); - importedProcessedModulesIDsParents.set( - importModuleIdWithExtension, - relativeModuleFilePath, - ); - } - }); - - if (!addedModulesRelativeToModulePath.has(relativeModuleFilePath)) { - const moduleData = { module: relativeModuleID, raw }; - updateRelativeModules(demoName, moduleData, variant); - addedModulesRelativeToModulePath.add(relativeModuleFilePath); } - } + }); + + updateRelativeModules(demoName, { module: relativeModuleID, raw }, variant); + addedModulesRelativeToModulePath.add(relativeModuleFilePath); + // iterate recursively over the relative imports while (importedProcessedModuleIDs.size > 0) { for (const entry of importedProcessedModuleIDs) { From 07f45cff4fc46fa40b0141ec2eac24408db48bf7 Mon Sep 17 00:00:00 2001 From: mnajdova Date: Wed, 30 Oct 2024 08:41:38 +0100 Subject: [PATCH 17/17] fix relativeModules map --- packages/markdown/loader.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/markdown/loader.js b/packages/markdown/loader.js index 22653ae21d2950..3b05c43194d004 100644 --- a/packages/markdown/loader.js +++ b/packages/markdown/loader.js @@ -489,7 +489,7 @@ module.exports = async function demoLoader() { extractImports(raw).forEach((importModuleID) => { // detect relative import const importModuleIdWithExtension = detectRelativeImports( - importModuleID, + relativeModuleID, relativeModuleFilePath, variant, importModuleID, @@ -523,7 +523,7 @@ module.exports = async function demoLoader() { extractImports(rawEntry).forEach((importModuleID) => { // detect relative import const importModuleIdWithExtension = detectRelativeImports( - entry, + relativeModuleID, entryModuleFilePath, variant, importModuleID,