diff --git a/packages/module/package.json b/packages/module/package.json index b28097a..27f0a6d 100644 --- a/packages/module/package.json +++ b/packages/module/package.json @@ -39,9 +39,9 @@ "tag": "prerelease" }, "dependencies": { - "@patternfly/react-core": "^5.0.0-prerelease.13", - "@patternfly/react-icons": "^5.0.0-prerelease.7", - "@patternfly/react-styles": "^5.0.0-prerelease.5", + "@patternfly/react-core": "^5.0.0-prerelease.26", + "@patternfly/react-icons": "^5.0.0-prerelease.9", + "@patternfly/react-styles": "^5.0.0-prerelease.7", "linear-layout-vector": "0.0.1", "react-virtualized": "^9.22.5", "tslib": "^2.5.2" @@ -51,12 +51,13 @@ "react-dom": "^17 || ^18" }, "devDependencies": { - "@patternfly/documentation-framework": "^2.0.0-alpha.69", - "@patternfly/patternfly": "^5.0.0-prerelease.10", - "@patternfly/react-table": "^5.0.0-prerelease.13", - "@patternfly/react-code-editor": "^5.0.0-prerelease.13", + "@patternfly/documentation-framework": "^5.0.15", + "@patternfly/patternfly": "^5.0.0-prerelease.16", + "@patternfly/react-table": "^5.0.0-prerelease.26", + "@patternfly/react-code-editor": "^5.0.0-prerelease.26", "rimraf": "^5.0.1", "@patternfly/patternfly-a11y": "^4.3.1", - "react-monaco-editor": "^0.52.0" + "react-monaco-editor": "^0.51.0", + "monaco-editor": "0.34.1" } } diff --git a/packages/module/patternfly-docs/content/examples/Actions.tsx b/packages/module/patternfly-docs/content/examples/Actions.tsx new file mode 100644 index 0000000..7441d3a --- /dev/null +++ b/packages/module/patternfly-docs/content/examples/Actions.tsx @@ -0,0 +1,149 @@ +/* eslint-disable no-console */ +import React from 'react'; +import { debounce } from '@patternfly/react-core'; +import { ActionsColumn, TableGridBreakpoint } from '@patternfly/react-table'; +import { Table as TableDeprecated, TableHeader as TableHeaderDeprecated } from '@patternfly/react-table/deprecated'; +import { CellMeasurerCache, CellMeasurer } from 'react-virtualized'; +import { AutoSizer, VirtualTableBody } from '@patternfly/react-virtualized-extension'; + +export class ActionsExample extends React.Component { + constructor(props) { + super(props); + const rows = []; + for (let i = 0; i < 100; i++) { + rows.push({ + disableActions: i % 3 === 2, + id: `actions-row-${i}`, + cells: [`one-${i}`, `two-${i}`, `three-${i}`, `four-${i}`, `five-${i}`] + }); + } + + this.actionsVirtualBody = null; + + this.state = { + columns: [ + { title: 'Name', props: { className: 'pf-m-6-col-on-sm pf-m-4-col-on-md pf-m-3-col-on-lg pf-m-2-col-on-xl' } }, + { + title: 'Namespace', + props: { className: 'pf-m-6-col-on-sm pf-m-4-col-on-md pf-m-3-col-on-lg pf-m-2-col-on-xl' } + }, + { + title: 'Labels', + props: { className: 'pf-m-4-col-on-md pf-m-4-col-on-lg pf-m-3-col-on-xl pf-m-hidden pf-m-visible-on-md' } + }, + { title: 'Status', props: { className: 'pf-m-2-col-on-lg pf-m-2-col-on-xl pf-m-hidden pf-m-visible-on-lg' } }, + { title: 'Pod Selector', props: { className: 'pf-m-2-col-on-xl pf-m-hidden pf-m-visible-on-xl' } }, + { title: '', props: { className: 'pf-v5-c-table__action' } } + ], + rows, + actions: [ + { + title: 'Some action', + onClick: (_event, rowId, _rowData, _extra) => console.log('clicked on Some action, on row: ', rowId) + }, + { + title:
Another action
, + onClick: (_event, rowId, _rowData, _extra) => console.log('clicked on Another action, on row: ', rowId) + }, + { + isSeparator: true + }, + { + title: 'Third action', + onClick: (_event, rowId, _rowData, _extra) => console.log('clicked on Third action, on row: ', rowId) + } + ] + }; + + this._handleResize = debounce(this._handleResize.bind(this), 100); + } + + componentDidMount() { + // re-render after resize + window.addEventListener('resize', this._handleResize); + } + + componentWillUnmount() { + window.removeEventListener('resize', this._handleResize); + } + + _handleResize() { + this.forceUpdate(); + } + + render() { + const { columns, rows } = this.state; + + const measurementCache = new CellMeasurerCache({ + fixedWidth: true, + minHeight: 44, + keyMapper: (rowIndex) => rowIndex + }); + + const rowRenderer = ({ index, _isScrolling, key, style, parent }) => { + const { rows, columns, actions } = this.state; + + return ( + + + + {rows[index].cells[0]} + + + {rows[index].cells[1]} + + + {rows[index].cells[2]} + + + {rows[index].cells[3]} + + + {rows[index].cells[4]} + + + + + + + ); + }; + + return ( +
+ + + + + {({ width }) => ( + (this.actionsVirtualBody = ref)} + className="pf-v5-c-table pf-v5-c-virtualized pf-v5-c-window-scroller" + deferredMeasurementCache={measurementCache} + rowHeight={measurementCache.rowHeight} + height={400} + overscanRowCount={2} + columnCount={1} + rows={rows} + rowCount={rows.length} + rowRenderer={rowRenderer} + width={width} + role="grid" + /> + )} + +
+ ); + } +} diff --git a/packages/module/patternfly-docs/content/examples/Basic.tsx b/packages/module/patternfly-docs/content/examples/Basic.tsx new file mode 100644 index 0000000..fa6a282 --- /dev/null +++ b/packages/module/patternfly-docs/content/examples/Basic.tsx @@ -0,0 +1,123 @@ +import React from 'react'; +import { debounce } from '@patternfly/react-core'; +import { TableGridBreakpoint } from '@patternfly/react-table'; +import { Table as TableDeprecated, TableHeader as TableHeaderDeprecated } from '@patternfly/react-table/deprecated'; +import { CellMeasurerCache, CellMeasurer } from 'react-virtualized'; +import { AutoSizer, VirtualTableBody } from '@patternfly/react-virtualized-extension'; + +export class VirtualizedExample extends React.Component { + constructor(props) { + super(props); + const rows = []; + for (let i = 0; i < 100; i++) { + rows.push({ + id: `basic-row-${i}`, + cells: [`one-${i}`, `two-${i}`, `three-${i}`, `four-${i}`, `five-${i}`] + }); + } + + this.state = { + columns: [ + { + title: 'Repositories', + props: { className: 'pf-m-6-col-on-sm pf-m-4-col-on-md pf-m-3-col-on-lg pf-m-2-col-on-xl' } + }, + { + title: 'Branches', + props: { className: 'pf-m-6-col-on-sm pf-m-4-col-on-md pf-m-3-col-on-lg pf-m-2-col-on-xl' } + }, + { + title: 'Pull requests', + props: { className: 'pf-m-4-col-on-md pf-m-4-col-on-lg pf-m-3-col-on-xl pf-m-hidden pf-m-visible-on-md' } + }, + { + title: 'Workspaces', + props: { className: 'pf-m-2-col-on-lg pf-m-2-col-on-xl pf-m-hidden pf-m-visible-on-lg' } + }, + { title: 'Last Commit', props: { className: 'pf-m-3-col-on-xl pf-m-hidden pf-m-visible-on-xl' } } + ], + rows + }; + this._handleResize = debounce(this._handleResize.bind(this), 100); + } + + componentDidMount() { + // re-render after resize + window.addEventListener('resize', this._handleResize); + } + + componentWillUnmount() { + window.removeEventListener('resize', this._handleResize); + } + + _handleResize() { + this.forceUpdate(); + } + + render() { + const { columns, rows } = this.state; + + const measurementCache = new CellMeasurerCache({ + fixedWidth: true, + minHeight: 44, + keyMapper: (rowIndex) => rowIndex + }); + + const rowRenderer = ({ index, _isScrolling, key, style, parent }) => { + const { rows, columns } = this.state; + + return ( + + + + {rows[index].cells[0]} + + + {rows[index].cells[1]} + + + {rows[index].cells[2]} + + + {rows[index].cells[3]} + + + {rows[index].cells[4]} + + + + ); + }; + + return ( +
+ + + + + {({ width }) => ( + + )} + +
+ ); + } +} diff --git a/packages/module/patternfly-docs/content/examples/FilterableWithWindowScroller.tsx b/packages/module/patternfly-docs/content/examples/FilterableWithWindowScroller.tsx new file mode 100644 index 0000000..5c08f14 --- /dev/null +++ b/packages/module/patternfly-docs/content/examples/FilterableWithWindowScroller.tsx @@ -0,0 +1,479 @@ +/* eslint-disable no-console */ +import React from 'react'; +import { + Button, + ButtonVariant, + Toolbar, + ToolbarItem, + ToolbarContent, + ToolbarFilter, + ToolbarToggleGroup, + ToolbarGroup, + InputGroup, + InputGroupItem, + TextInput +} from '@patternfly/react-core'; +import { debounce } from '@patternfly/react-core'; +import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon'; +import FilterIcon from '@patternfly/react-icons/dist/esm/icons/filter-icon'; +import { ActionsColumn } from '@patternfly/react-table'; +import { Table as TableDeprecated, TableHeader as TableHeaderDeprecated } from '@patternfly/react-table/deprecated'; +import { + Dropdown as DropdownDeprecated, + DropdownItem as DropdownItemDeprecated, + DropdownPosition as DropdownPositionDeprecated, + DropdownToggle as DropdownToggleDeprecated, + Select as SelectDeprecated, + SelectOption as SelectOptionDeprecated, + SelectVariant as SelectVariantDeprecated +} from '@patternfly/react-core/deprecated'; +import { CellMeasurerCache, CellMeasurer } from 'react-virtualized'; +import { AutoSizer, VirtualTableBody, WindowScroller } from '@patternfly/react-virtualized-extension'; + +export class FilterExample extends React.Component { + constructor(props) { + super(props); + + this.actionsVirtualBody = null; + + const rows = []; + for (let i = 0; i < 100; i++) { + const data = {}; + if (i % 2 === 0) { + data.cells = [`US-Node ${i}`, i, i, 'Down', 'Brno']; + } else if (i % 3 === 0) { + data.cells = [`CN-Node ${i}`, i, i, 'Running', 'Westford']; + } else { + data.cells = [`US-Node ${i}`, i, i, 'Stopped', 'Raleigh']; + } + rows.push(data); + } + this.scrollableElement = React.createRef(); + + this.state = { + scrollableElement: null, + + filters: { + location: [], + name: [], + status: [] + }, + currentCategory: 'Name', + isFilterDropdownOpen: false, + isCategoryDropdownOpen: false, + nameInput: '', + columns: [ + { title: 'Servers' }, + { title: 'Threads' }, + { title: 'Applications' }, + { title: 'Status' }, + { title: 'Location' } + ], + rows, + inputValue: '', + actions: [ + { + title: 'Some action', + onClick: (_event, rowId, _rowData, _extra) => console.log('clicked on Some action, on row: ', rowId) + }, + { + title:
Another action
, + onClick: (_event, rowId, _rowData, _extra) => console.log('clicked on Another action, on row: ', rowId) + }, + { + isSeparator: true + }, + { + title: 'Third action', + onClick: (_event, rowId, _rowData, _extra) => console.log('clicked on Third action, on row: ', rowId) + } + ] + }; + + this._handleResize = debounce(this._handleResize.bind(this), 100); + + this.onDelete = (type = '', id = '') => { + if (type) { + this.setState((prevState) => { + prevState.filters[type.toLowerCase()] = prevState.filters[type.toLowerCase()].filter((s) => s !== id); + return { + filters: prevState.filters + }; + }); + } else { + this.setState({ + filters: { + location: [], + name: [], + status: [] + }, + inputValue: '' + }); + } + }; + + this.onCategoryToggle = (_event, isOpen) => { + this.setState({ + isCategoryDropdownOpen: isOpen + }); + }; + + this.onCategorySelect = (event) => { + this.setState({ + currentCategory: event.target.innerText, + isCategoryDropdownOpen: !this.state.isCategoryDropdownOpen + }); + }; + + this.onFilterToggle = (_event, isOpen) => { + this.setState({ + isFilterDropdownOpen: isOpen + }); + }; + + this.onFilterSelect = (_event) => { + this.setState({ + isFilterDropdownOpen: !this.state.isFilterDropdownOpen + }); + }; + + this.onInputChange = (_event, newValue) => { + // this.setState({ inputValue: newValue }); + if (newValue === '') { + this.onDelete(); + this.setState({ + inputValue: newValue + }); + } else { + this.setState((prevState) => ({ + filters: { + ...prevState.filters, + ['name']: [newValue] + }, + inputValue: newValue + })); + } + }; + + this.onRowSelect = (event, isSelected, rowId) => { + let rows; + if (rowId === -1) { + rows = this.state.rows.map((oneRow) => { + oneRow.selected = isSelected; + return oneRow; + }); + } else { + rows = [...this.state.rows]; + rows[rowId].selected = isSelected; + } + this.setState({ + rows + }); + }; + + this.onStatusSelect = (event, selection) => { + const checked = event.target.checked; + this.setState((prevState) => { + const prevSelections = prevState.filters.status; + return { + filters: { + ...prevState.filters, + status: checked ? [...prevSelections, selection] : prevSelections.filter((value) => value !== selection) + } + }; + }); + }; + + this.onNameInput = (event) => { + if (event.key && event.key !== 'Enter') { + return; + } + + const { inputValue } = this.state; + this.setState((prevState) => { + const prevFilters = prevState.filters.name; + return { + filters: { + ...prevState.filters, + ['name']: prevFilters.includes(inputValue) ? prevFilters : [...prevFilters, inputValue] + }, + inputValue: '' + }; + }); + }; + + this.onLocationSelect = (event, selection) => { + this.setState((prevState) => ({ + filters: { + ...prevState.filters, + ['location']: [selection] + } + })); + this.onFilterSelect(); + }; + + this._handleResize = debounce(this._handleResize.bind(this), 100); + this._bindBodyRef = this._bindBodyRef.bind(this); + } + + componentDidMount() { + // re-render after resize + window.addEventListener('resize', this._handleResize); + + setTimeout(() => { + const scollableElement = document.getElementById('content-scrollable-1'); + this.setState({ scollableElement }); + }); + + // re-render after resize + window.addEventListener('resize', this._handleResize); + } + + componentWillUnmount() { + window.removeEventListener('resize', this._handleResize); + } + + _handleResize() { + this._cellMeasurementCache.clearAll(); + this._bodyRef.recomputeVirtualGridSize(); + } + + _bindBodyRef(ref) { + this._bodyRef = ref; + } + + buildCategoryDropdown() { + const { isCategoryDropdownOpen, currentCategory } = this.state; + + return ( + + + {currentCategory} + + } + isOpen={isCategoryDropdownOpen} + dropdownItems={[ + Location, + Name, + Status + ]} + style={{ width: '100%' }} + > + + ); + } + + buildFilterDropdown() { + const { currentCategory, isFilterDropdownOpen, inputValue, filters } = this.state; + + const locationMenuItems = [ + , + , + , + , + + ]; + + const statusMenuItems = [ + , + , + , + , + + ]; + + return ( + + + + {locationMenuItems} + + + + + + + + + + + + + + + {statusMenuItems} + + + + ); + } + + renderToolbar() { + return ( + + + } breakpoint="xl"> + + {this.buildCategoryDropdown()} + {this.buildFilterDropdown()} + + + + + ); + } + + render() { + const { loading, rows, columns, actions, filters, scollableElement } = this.state; + + const filteredRows = + filters.name.length > 0 || filters.location.length > 0 || filters.status.length > 0 + ? rows.filter((row) => ( + (filters.name.length === 0 || + filters.name.some((name) => row.cells[0].toLowerCase().includes(name.toLowerCase()))) && + (filters.location.length === 0 || filters.location.includes(row.cells[4])) && + (filters.status.length === 0 || filters.status.includes(row.cells[3])) + )) + : rows; + const measurementCache = new CellMeasurerCache({ + fixedWidth: true, + minHeight: 44, + keyMapper: (rowIndex) => rowIndex + }); + + const rowRenderer = ({ index, _isScrolling, key, style, parent }) => { + const { actions } = this.state; + + return ( + + + {filteredRows[index].cells[0]} + {filteredRows[index].cells[1]} + {filteredRows[index].cells[2]} + {filteredRows[index].cells[3]} + {filteredRows[index].cells[4]} + + + + + + ); + }; + + return ( + + {this.renderToolbar()} + +
+
+ {!loading && filteredRows.length > 0 && ( +
+ + + + + {({ height, _isScrolling, registerChild, _onChildScroll, scrollTop }) => ( + + {({ width }) => ( +
+ (this.actionsVirtualBody = ref)} + autoHeight + className="pf-v5-c-table pf-v5-c-virtualized pf-v5-c-window-scroller" + deferredMeasurementCache={measurementCache} + rowHeight={measurementCache.rowHeight} + height={height || 0} + overscanRowCount={10} + columnCount={6} + rows={filteredRows} + rowCount={filteredRows.length} + rowRenderer={rowRenderer} + scrollTop={scrollTop} + width={width} + role="grid" + /> +
+ )} +
+ )} +
+
+ )} +
+
+
+ ); + } +} diff --git a/packages/module/patternfly-docs/content/examples/Selectable.tsx b/packages/module/patternfly-docs/content/examples/Selectable.tsx new file mode 100644 index 0000000..3110aac --- /dev/null +++ b/packages/module/patternfly-docs/content/examples/Selectable.tsx @@ -0,0 +1,153 @@ +import React from 'react'; +import { debounce } from '@patternfly/react-core'; +import { headerCol, TableGridBreakpoint } from '@patternfly/react-table'; +import { Table as TableDeprecated, TableHeader as TableHeaderDeprecated } from '@patternfly/react-table/deprecated'; +import { CellMeasurerCache, CellMeasurer } from 'react-virtualized'; +import { AutoSizer, VirtualTableBody } from '@patternfly/react-virtualized-extension'; + +export class SelectableExample extends React.Component { + constructor(props) { + super(props); + const rows = []; + for (let i = 0; i < 100; i++) { + rows.push({ + selected: false, + id: `selectable-row-${i}`, + cells: [`one-${i}`, `two-${i}`, `three-${i}`, `four-${i}`, `five-${i}`] + }); + } + + this.selectableVirtualBody = null; + + this.state = { + columns: [ + // headerCol transform adds checkbox column with pf-m-2-sm, pf-m-1-md+ column space + { + title: 'Repositories', + cellTransforms: [headerCol()], + props: { className: 'pf-m-5-col-on-sm pf-m-4-col-on-md pf-m-3-col-on-lg pf-m-2-col-on-xl' } + }, + { + title: 'Pull requests', + props: { className: 'pf-m-5-col-on-sm pf-m-4-col-on-md pf-m-4-col-on-lg pf-m-3-col-on-xl' } + }, + { + title: 'Workspaces', + props: { className: 'pf-m-2-col-on-lg pf-m-2-col-on-xl pf-m-hidden pf-m-visible-on-lg' } + }, + { title: 'Last Commit', props: { className: 'pf-m-3-col-on-xl pf-m-hidden pf-m-visible-on-xl' } } + ], + rows + }; + + this.onSelect = this.onSelect.bind(this); + this._handleResize = debounce(this._handleResize.bind(this), 100); + } + + componentDidMount() { + // re-render after resize + window.addEventListener('resize', this._handleResize); + } + + componentWillUnmount() { + window.removeEventListener('resize', this._handleResize); + } + + _handleResize() { + this.forceUpdate(); + } + + onSelect(event, isSelected, virtualRowIndex, rowData) { + let rows; + if (virtualRowIndex === -1) { + rows = this.state.rows.map((oneRow) => { + oneRow.selected = isSelected; + return oneRow; + }); + } else { + rows = [...this.state.rows]; + const rowIndex = rows.findIndex((r) => r.id === rowData.id); + rows[rowIndex] = { ...rows[rowIndex], selected: isSelected }; + } + this.setState({ + rows + }); + this.selectableVirtualBody.forceUpdateVirtualGrid(); + } + + render() { + const { columns, rows } = this.state; + + const measurementCache = new CellMeasurerCache({ + fixedWidth: true, + minHeight: 44, + keyMapper: (rowIndex) => rowIndex + }); + + const rowRenderer = ({ index, _isScrolling, key, style, parent }) => { + const { rows, columns } = this.state; + + return ( + + + + { + this.onSelect(e, e.target.checked, 0, { id: rows[index].id }); + }} + /> + + + {rows[index].cells[0]} + + + {rows[index].cells[1]} + + + {rows[index].cells[2]} + + + {rows[index].cells[3]} + + + + ); + }; + + return ( +
+ + + + + {({ width }) => ( + (this.selectableVirtualBody = ref)} + className="pf-v5-c-table pf-v5-c-virtualized pf-v5-c-window-scroller" + deferredMeasurementCache={measurementCache} + rowHeight={measurementCache.rowHeight} + height={400} + overscanRowCount={2} + columnCount={1} + rows={rows} + rowCount={rows.length} + rowRenderer={rowRenderer} + width={width} + role="grid" + /> + )} + +
+ ); + } +} diff --git a/packages/module/patternfly-docs/content/examples/Sortable.tsx b/packages/module/patternfly-docs/content/examples/Sortable.tsx new file mode 100644 index 0000000..eb2418d --- /dev/null +++ b/packages/module/patternfly-docs/content/examples/Sortable.tsx @@ -0,0 +1,150 @@ +import React from 'react'; +import { debounce } from '@patternfly/react-core'; +import { sortable, SortByDirection, TableGridBreakpoint } from '@patternfly/react-table'; +import { Table as TableDeprecated, TableHeader as TableHeaderDeprecated } from '@patternfly/react-table/deprecated'; +import { CellMeasurerCache, CellMeasurer } from 'react-virtualized'; +import { AutoSizer, VirtualTableBody } from '@patternfly/react-virtualized-extension'; + +export class SortableExample extends React.Component { + constructor(props) { + super(props); + const rows = []; + for (let i = 0; i < 100; i++) { + rows.push({ + id: `sortable-row-${i}`, + cells: [`one-${i}`, `two-${i}`, `three-${i}`, `four-${i}`, `five-${i}`] + }); + } + + this.sortableVirtualBody = null; + + this.state = { + columns: [ + { + title: 'Repositories', + transforms: [sortable], + props: { className: 'pf-m-6-col-on-sm pf-m-4-col-on-md pf-m-3-col-on-lg pf-m-2-col-on-xl' } + }, + { + title: 'Branches', + props: { className: 'pf-m-6-col-on-sm pf-m-4-col-on-md pf-m-3-col-on-lg pf-m-2-col-on-xl' } + }, + { + title: 'Pull requests', + transforms: [sortable], + props: { className: 'pf-m-4-col-on-md pf-m-4-col-on-lg pf-m-3-col-on-xl pf-m-hidden pf-m-visible-on-md' } + }, + { + title: 'Workspaces', + props: { className: 'pf-m-2-col-on-lg pf-m-2-col-on-xl pf-m-hidden pf-m-visible-on-lg' } + }, + { title: 'Last Commit', props: { className: 'pf-m-3-col-on-xl pf-m-hidden pf-m-visible-on-xl' } } + ], + rows, + sortBy: {} + }; + + this.onSort = this.onSort.bind(this); + this._handleResize = debounce(this._handleResize.bind(this), 100); + } + + componentDidMount() { + // re-render after resize + window.addEventListener('resize', this._handleResize); + } + + componentWillUnmount() { + window.removeEventListener('resize', this._handleResize); + } + + _handleResize() { + this.forceUpdate(); + } + + onSort(_event, index, direction) { + const sortedRows = this.state.rows.sort((a, b) => + // eslint-disable-next-line no-nested-ternary + a.cells[index] < b.cells[index] ? -1 : a.cells[index] > b.cells[index] ? 1 : 0 + ); + this.setState({ + sortBy: { + index, + direction + }, + rows: direction === SortByDirection.asc ? sortedRows : sortedRows.reverse() + }); + + this.sortableVirtualBody.forceUpdateVirtualGrid(); + } + + render() { + const { sortBy, columns, rows } = this.state; + + const measurementCache = new CellMeasurerCache({ + fixedWidth: true, + minHeight: 44, + keyMapper: (rowIndex) => rowIndex + }); + + const rowRenderer = ({ index, _isScrolling, key, style, parent }) => { + const { rows, columns } = this.state; + + return ( + + + + {rows[index].cells[0]} + + + {rows[index].cells[1]} + + + {rows[index].cells[2]} + + + {rows[index].cells[3]} + + + {rows[index].cells[4]} + + + + ); + }; + + return ( +
+ + + + + {({ width }) => ( + (this.sortableVirtualBody = ref)} + className="pf-v5-c-table pf-v5-c-virtualized pf-v5-c-window-scroller" + deferredMeasurementCache={measurementCache} + rowHeight={measurementCache.rowHeight} + height={400} + overscanRowCount={2} + columnCount={1} + rows={rows} + rowCount={rows.length} + rowRenderer={rowRenderer} + width={width} + role="grid" + /> + )} + +
+ ); + } +} diff --git a/packages/module/patternfly-docs/content/examples/UsingComposableTableComponents.tsx b/packages/module/patternfly-docs/content/examples/UsingComposableTableComponents.tsx new file mode 100644 index 0000000..15933a9 --- /dev/null +++ b/packages/module/patternfly-docs/content/examples/UsingComposableTableComponents.tsx @@ -0,0 +1,75 @@ +import React from 'react'; + +import { CellMeasurerCache, CellMeasurer } from 'react-virtualized'; +import { AutoSizer, VirtualTableBody } from '@patternfly/react-virtualized-extension'; +import { Table, Thead, Tr, Th, Td, Caption, TableGridBreakpoint } from '@patternfly/react-table'; + +export const ComposableTableVirtualized = () => { + const rows = []; + for (let i = 0; i < 100; i++) { + rows.push([`one-${i}`, `two-${i}`, `three-${i}`, `four-${i}`, `five-${i}`]); + } + const [selected, setSelected] = React.useState(rows.map((_row) => false)); + const columns = ['Repositories', 'Branches', 'Pull requests', 'Workspaces', 'Last Commit']; + + const onSelect = (event, isSelected, rowId) => { + setSelected(selected.map((sel, index) => (index === rowId ? isSelected : sel))); + }; + + const measurementCache = new CellMeasurerCache({ + fixedWidth: true, + minHeight: 44, + keyMapper: (rowIndex) => rowIndex + }); + + const rowRenderer = ({ index: rowIndex, _isScrolling, key, style, parent }) => ( + + + + {columns.map((col, index) => ( + {rows[rowIndex][index]} + ))} + + + ); + + return ( +
+ + + + + + ))} + + +
Virtualized table with composable table components
+ {columns.map((col, index) => ( + {col}
+ + {({ width }) => ( + + )} + +
+ ); +}; diff --git a/packages/module/patternfly-docs/content/examples/UsingComposableTableComponentsDemo.tsx b/packages/module/patternfly-docs/content/examples/UsingComposableTableComponentsDemo.tsx new file mode 100644 index 0000000..ea411ea --- /dev/null +++ b/packages/module/patternfly-docs/content/examples/UsingComposableTableComponentsDemo.tsx @@ -0,0 +1,116 @@ +import React from 'react'; +import { CellMeasurerCache, CellMeasurer } from 'react-virtualized'; +import { AutoSizer, VirtualTableBody, WindowScroller } from '@patternfly/react-virtualized-extension'; +import { Table, Thead, Tr, Th, Td, Caption, TableGridBreakpoint } from '@patternfly/react-table'; + +export const ComposableTableWindowScroller = () => { + const [scrollableElement, setScrollableElement] = React.useState(); + React.useEffect(() => { + const scrollableElement = document.getElementById('content-scrollable-2'); + setScrollableElement(scrollableElement); + }); + const rows = []; + for (let i = 0; i < 100000; i++) { + const cells = []; + const num = Math.floor(Math.random() * Math.floor(2)) + 1; + for (let j = 0; j < 5; j++) { + const cellValue = i.toString() + ' Arma virumque cano Troiae qui primus ab oris. '.repeat(num); + cells.push(cellValue); + } + rows.push(cells); + } + const [selected, setSelected] = React.useState(rows.map((_row) => false)); + const columns = ['Repositories', 'Branches', 'Pull requests', 'Workspaces', 'Last Commit']; + const scrollToIndex = -1; // can be used to programmatically set current index + + const onSelect = (event, isSelected, rowId) => { + setSelected(selected.map((sel, index) => (index === rowId ? isSelected : sel))); + }; + + const measurementCache = new CellMeasurerCache({ + fixedWidth: true, + minHeight: 44, + keyMapper: (rowIndex) => rowIndex + }); + + const rowRenderer = ({ index: rowIndex, _isScrolling, key, style, parent }) => { + const text = rows[rowIndex][0]; + + return ( + + + + {columns.map((col, index) => ( + {text} + ))} + + + ); + }; + + const scrollableContainerStyle = { + height: 500 /* important note: the scrollable container should have some sort of fixed height, or it should be wrapped in container that is smaller than ReactVirtualized__VirtualGrid container and has overflow visible if using the Window Scroller. See WindowScroller.example.css */, + overflowX: 'auto', + overflowY: 'scroll', + scrollBehavior: 'smooth', + WebkitOverflowScrolling: 'touch', + position: 'relative' + }; + + return ( +
+ + + + + + ))} + + +
Virtualized table with composable table components
+ {columns.map((col, index) => ( + {col}
+ + {({ height, isScrolling, registerChild, onChildScroll, scrollTop }) => ( + + {({ width }) => ( +
+ +
+ )} +
+ )} +
+
+ ); +}; diff --git a/packages/module/patternfly-docs/content/examples/VirtualizedTable.md b/packages/module/patternfly-docs/content/examples/VirtualizedTable.md index 5dfdf03..ff6f736 100644 --- a/packages/module/patternfly-docs/content/examples/VirtualizedTable.md +++ b/packages/module/patternfly-docs/content/examples/VirtualizedTable.md @@ -14,13 +14,13 @@ import { CellMeasurerCache, CellMeasurer} from 'react-virtualized'; import { AutoSizer, VirtualTableBody, WindowScroller } from '@patternfly/react-virtualized-extension'; import { Table as TableDeprecated, TableHeader as TableHeaderDeprecated } from '@patternfly/react-table/deprecated'; import { - Dropdown, - DropdownItem, - DropdownPosition, - DropdownToggle, - Select, - SelectOption, - SelectVariant + Dropdown as DropdownDeprecated, + DropdownItem as DropdownItemDeprecated, + DropdownPosition as DropdownPositionDeprecated, + DropdownToggle as DropdownToggleDeprecated, + Select as SelectDeprecated, + SelectOption as SelectOptionDeprecated, + SelectVariant as SelectVariantDeprecated } from '@patternfly/react-core/deprecated'; import './VirtualGrid.example.css'; @@ -28,1162 +28,30 @@ import './VirtualGrid.example.css'; ### Basic -```js -import React from 'react'; -import { debounce } from '@patternfly/react-core'; -import { TableGridBreakpoint } from '@patternfly/react-table'; -import { Table as TableDeprecated, TableHeader as TableHeaderDeprecated } from '@patternfly/react-table/deprecated'; -import { CellMeasurerCache, CellMeasurer } from 'react-virtualized'; -import { AutoSizer, VirtualTableBody } from '@patternfly/react-virtualized-extension'; - -class VirtualizedExample extends React.Component { - constructor(props) { - super(props); - const rows = []; - for (let i = 0; i < 100; i++) { - rows.push({ - id: `basic-row-${i}`, - cells: [`one-${i}`, `two-${i}`, `three-${i}`, `four-${i}`, `five-${i}`] - }); - } - - this.state = { - columns: [ - { - title: 'Repositories', - props: { className: 'pf-m-6-col-on-sm pf-m-4-col-on-md pf-m-3-col-on-lg pf-m-2-col-on-xl' } - }, - { - title: 'Branches', - props: { className: 'pf-m-6-col-on-sm pf-m-4-col-on-md pf-m-3-col-on-lg pf-m-2-col-on-xl' } - }, - { - title: 'Pull requests', - props: { className: 'pf-m-4-col-on-md pf-m-4-col-on-lg pf-m-3-col-on-xl pf-m-hidden pf-m-visible-on-md' } - }, - { - title: 'Workspaces', - props: { className: 'pf-m-2-col-on-lg pf-m-2-col-on-xl pf-m-hidden pf-m-visible-on-lg' } - }, - { title: 'Last Commit', props: { className: 'pf-m-3-col-on-xl pf-m-hidden pf-m-visible-on-xl' } } - ], - rows - }; - this._handleResize = debounce(this._handleResize.bind(this), 100); - } - - componentDidMount() { - // re-render after resize - window.addEventListener('resize', this._handleResize); - } - - componentWillUnmount() { - window.removeEventListener('resize', this._handleResize); - } - - _handleResize() { - this.forceUpdate(); - } - - render() { - const { columns, rows } = this.state; - - const measurementCache = new CellMeasurerCache({ - fixedWidth: true, - minHeight: 44, - keyMapper: rowIndex => rowIndex - }); - - const rowRenderer = ({ index, isScrolling, key, style, parent }) => { - const { rows, columns } = this.state; - - return ( - - - - {rows[index].cells[0]} - - - {rows[index].cells[1]} - - - {rows[index].cells[2]} - - - {rows[index].cells[3]} - - - {rows[index].cells[4]} - - - - ); - }; - - return ( -
- - - - - {({ width }) => ( - - )} - -
- ); - } -} +```js file="./Basic.tsx" ``` ### Using composable table components -```js -import React from 'react'; -import { debounce } from '@patternfly/react-core'; -import { CellMeasurerCache, CellMeasurer } from 'react-virtualized'; -import { AutoSizer, VirtualTableBody } from '@patternfly/react-virtualized-extension'; -import { Table, Thead, Tr, Th, Td, Caption, TableGridBreakpoint } from '@patternfly/react-table'; - -ComposableTableVirtualized = () => { - const rows = []; - for (let i = 0; i < 100; i++) { - rows.push([`one-${i}`, `two-${i}`, `three-${i}`, `four-${i}`, `five-${i}`]); - } - const [selected, setSelected] = React.useState(rows.map(row => false)); - const columns = [ - 'Repositories', 'Branches', 'Pull requests', 'Workspaces', 'Last Commit' - ]; - - const onSelect = (event, isSelected, rowId) => { - setSelected(selected.map((sel, index) => (index === rowId ? isSelected : sel))); - }; - - const measurementCache = new CellMeasurerCache({ - fixedWidth: true, - minHeight: 44, - keyMapper: rowIndex => rowIndex - }); - - const rowRenderer = ({ index: rowIndex, isScrolling, key, style, parent }) => ( - - - - {columns.map((col, index) => ( - - {rows[rowIndex][index]} - - ))} - - - ); - - return ( -
- - - - - - ))} - - -
Virtualized table with composable table components
- {columns.map((col, index) => ( - - {col} -
- - {({ width }) => ( - - )} - -
- ); -}; +```js file="./UsingComposableTableComponents.tsx" ``` ### Sortable -```js -import React from 'react'; -import { debounce } from '@patternfly/react-core'; -import { sortable, SortByDirection, TableGridBreakpoint } from '@patternfly/react-table'; -import { Table as TableDeprecated, TableHeader as TableHeaderDeprecated } from '@patternfly/react-table/deprecated'; -import { CellMeasurerCache, CellMeasurer } from 'react-virtualized'; -import { AutoSizer, VirtualTableBody } from '@patternfly/react-virtualized-extension'; - -class SortableExample extends React.Component { - constructor(props) { - super(props); - const rows = []; - for (let i = 0; i < 100; i++) { - rows.push({ - id: `sortable-row-${i}`, - cells: [`one-${i}`, `two-${i}`, `three-${i}`, `four-${i}`, `five-${i}`] - }); - } - - this.sortableVirtualBody = null; - - this.state = { - columns: [ - { - title: 'Repositories', - transforms: [sortable], - props: { className: 'pf-m-6-col-on-sm pf-m-4-col-on-md pf-m-3-col-on-lg pf-m-2-col-on-xl' } - }, - { - title: 'Branches', - props: { className: 'pf-m-6-col-on-sm pf-m-4-col-on-md pf-m-3-col-on-lg pf-m-2-col-on-xl' } - }, - { - title: 'Pull requests', - transforms: [sortable], - props: { className: 'pf-m-4-col-on-md pf-m-4-col-on-lg pf-m-3-col-on-xl pf-m-hidden pf-m-visible-on-md' } - }, - { - title: 'Workspaces', - props: { className: 'pf-m-2-col-on-lg pf-m-2-col-on-xl pf-m-hidden pf-m-visible-on-lg' } - }, - { title: 'Last Commit', props: { className: 'pf-m-3-col-on-xl pf-m-hidden pf-m-visible-on-xl' } } - ], - rows, - sortBy: {} - }; - - this.onSort = this.onSort.bind(this); - this._handleResize = debounce(this._handleResize.bind(this), 100); - } - - componentDidMount() { - // re-render after resize - window.addEventListener('resize', this._handleResize); - } - - componentWillUnmount() { - window.removeEventListener('resize', this._handleResize); - } - - _handleResize() { - this.forceUpdate(); - } - - onSort(_event, index, direction) { - const sortedRows = this.state.rows.sort((a, b) => - a.cells[index] < b.cells[index] ? -1 : a.cells[index] > b.cells[index] ? 1 : 0 - ); - this.setState({ - sortBy: { - index, - direction - }, - rows: direction === SortByDirection.asc ? sortedRows : sortedRows.reverse() - }); - - this.sortableVirtualBody.forceUpdateVirtualGrid(); - } - - render() { - const { sortBy, columns, rows } = this.state; - - const measurementCache = new CellMeasurerCache({ - fixedWidth: true, - minHeight: 44, - keyMapper: rowIndex => rowIndex - }); - - const rowRenderer = ({ index, isScrolling, key, style, parent }) => { - const { rows, columns } = this.state; - - return ( - - - - {rows[index].cells[0]} - - - {rows[index].cells[1]} - - - {rows[index].cells[2]} - - - {rows[index].cells[3]} - - - {rows[index].cells[4]} - - - - ); - }; - - return ( -
- - - - - {({ width }) => ( - (this.sortableVirtualBody = ref)} - className="pf-v5-c-table pf-v5-c-virtualized pf-v5-c-window-scroller" - deferredMeasurementCache={measurementCache} - rowHeight={measurementCache.rowHeight} - height={400} - overscanRowCount={2} - columnCount={1} - rows={rows} - rowCount={rows.length} - rowRenderer={rowRenderer} - width={width} - role="grid" - /> - )} - -
- ); - } -} +```js file="./Sortable.tsx" ``` ### Selectable -```js -import React from 'react'; -import { debounce } from '@patternfly/react-core'; -import { headerCol, TableGridBreakpoint } from '@patternfly/react-table'; -import { Table as TableDeprecated, TableHeader as TableHeaderDeprecated } from '@patternfly/react-table/deprecated'; -import { CellMeasurerCache, CellMeasurer } from 'react-virtualized'; -import { AutoSizer, VirtualTableBody } from '@patternfly/react-virtualized-extension'; - -class SelectableExample extends React.Component { - constructor(props) { - super(props); - const rows = []; - for (let i = 0; i < 100; i++) { - rows.push({ - selected: false, - id: `selectable-row-${i}`, - cells: [`one-${i}`, `two-${i}`, `three-${i}`, `four-${i}`, `five-${i}`] - }); - } - - this.selectableVirtualBody = null; - - this.state = { - columns: [ - // headerCol transform adds checkbox column with pf-m-2-sm, pf-m-1-md+ column space - { - title: 'Repositories', - cellTransforms: [headerCol()], - props: { className: 'pf-m-5-col-on-sm pf-m-4-col-on-md pf-m-3-col-on-lg pf-m-2-col-on-xl' } - }, - { - title: 'Pull requests', - props: { className: 'pf-m-5-col-on-sm pf-m-4-col-on-md pf-m-4-col-on-lg pf-m-3-col-on-xl' } - }, - { - title: 'Workspaces', - props: { className: 'pf-m-2-col-on-lg pf-m-2-col-on-xl pf-m-hidden pf-m-visible-on-lg' } - }, - { title: 'Last Commit', props: { className: 'pf-m-3-col-on-xl pf-m-hidden pf-m-visible-on-xl' } } - ], - rows - }; - - this.onSelect = this.onSelect.bind(this); - this._handleResize = debounce(this._handleResize.bind(this), 100); - } - - componentDidMount() { - // re-render after resize - window.addEventListener('resize', this._handleResize); - } - - componentWillUnmount() { - window.removeEventListener('resize', this._handleResize); - } - - _handleResize() { - this.forceUpdate(); - } - - onSelect(event, isSelected, virtualRowIndex, rowData) { - let rows; - if (virtualRowIndex === -1) { - rows = this.state.rows.map(oneRow => { - oneRow.selected = isSelected; - return oneRow; - }); - } else { - rows = [...this.state.rows]; - const rowIndex = rows.findIndex(r => r.id === rowData.id); - rows[rowIndex] = { ...rows[rowIndex], selected: isSelected }; - } - this.setState({ - rows - }); - this.selectableVirtualBody.forceUpdateVirtualGrid(); - } - - render() { - const { columns, rows } = this.state; - - const measurementCache = new CellMeasurerCache({ - fixedWidth: true, - minHeight: 44, - keyMapper: rowIndex => rowIndex - }); - - const rowRenderer = ({ index, isScrolling, key, style, parent }) => { - const { rows, columns } = this.state; - - return ( - - - - { - this.onSelect(e, e.target.checked, 0, { id: rows[index].id }); - }} - /> - - - {rows[index].cells[0]} - - - {rows[index].cells[1]} - - - {rows[index].cells[2]} - - - {rows[index].cells[3]} - - - - ); - }; - - return ( -
- - - - - {({ width }) => ( - (this.selectableVirtualBody = ref)} - className="pf-v5-c-table pf-v5-c-virtualized pf-v5-c-window-scroller" - deferredMeasurementCache={measurementCache} - rowHeight={measurementCache.rowHeight} - height={400} - overscanRowCount={2} - columnCount={1} - rows={rows} - rowCount={rows.length} - rowRenderer={rowRenderer} - width={width} - role="grid" - /> - )} - -
- ); - } -} +```js file="./Selectable.tsx" ``` ### Actions -```js -import React from 'react'; -import { debounce } from '@patternfly/react-core'; -import { ActionsColumn, TableGridBreakpoint } from '@patternfly/react-table'; -import { Table as TableDeprecated, TableHeader as TableHeaderDeprecated } from '@patternfly/react-table/deprecated'; -import { CellMeasurerCache, CellMeasurer } from 'react-virtualized'; -import { AutoSizer, VirtualTableBody } from '@patternfly/react-virtualized-extension'; - -class ActionsExample extends React.Component { - constructor(props) { - super(props); - const rows = []; - for (let i = 0; i < 100; i++) { - rows.push({ - disableActions: i % 3 === 2, - id: `actions-row-${i}`, - cells: [`one-${i}`, `two-${i}`, `three-${i}`, `four-${i}`, `five-${i}`] - }); - } - - this.actionsVirtualBody = null; - - this.state = { - columns: [ - { title: 'Name', props: { className: 'pf-m-6-col-on-sm pf-m-4-col-on-md pf-m-3-col-on-lg pf-m-2-col-on-xl' } }, - { - title: 'Namespace', - props: { className: 'pf-m-6-col-on-sm pf-m-4-col-on-md pf-m-3-col-on-lg pf-m-2-col-on-xl' } - }, - { - title: 'Labels', - props: { className: 'pf-m-4-col-on-md pf-m-4-col-on-lg pf-m-3-col-on-xl pf-m-hidden pf-m-visible-on-md' } - }, - { title: 'Status', props: { className: 'pf-m-2-col-on-lg pf-m-2-col-on-xl pf-m-hidden pf-m-visible-on-lg' } }, - { title: 'Pod Selector', props: { className: 'pf-m-2-col-on-xl pf-m-hidden pf-m-visible-on-xl' } }, - { title: '', props: { className: 'pf-v5-c-table__action' } } - ], - rows, - actions: [ - { - title: 'Some action', - onClick: (event, rowId, rowData, extra) => console.log('clicked on Some action, on row: ', rowId) - }, - { - title:
Another action
, - onClick: (event, rowId, rowData, extra) => console.log('clicked on Another action, on row: ', rowId) - }, - { - isSeparator: true - }, - { - title: 'Third action', - onClick: (event, rowId, rowData, extra) => console.log('clicked on Third action, on row: ', rowId) - } - ] - }; - - this._handleResize = debounce(this._handleResize.bind(this), 100); - } - - componentDidMount() { - // re-render after resize - window.addEventListener('resize', this._handleResize); - } - - componentWillUnmount() { - window.removeEventListener('resize', this._handleResize); - } - - _handleResize() { - this.forceUpdate(); - } - - render() { - const { columns, rows } = this.state; - - const measurementCache = new CellMeasurerCache({ - fixedWidth: true, - minHeight: 44, - keyMapper: rowIndex => rowIndex - }); - - const rowRenderer = ({ index, isScrolling, key, style, parent }) => { - const { rows, columns, actions } = this.state; - - return ( - - - - {rows[index].cells[0]} - - - {rows[index].cells[1]} - - - {rows[index].cells[2]} - - - {rows[index].cells[3]} - - - {rows[index].cells[4]} - - - - - - - ); - }; - - return ( -
- - - - - {({ width }) => ( - (this.actionsVirtualBody = ref)} - className="pf-v5-c-table pf-v5-c-virtualized pf-v5-c-window-scroller" - deferredMeasurementCache={measurementCache} - rowHeight={measurementCache.rowHeight} - height={400} - overscanRowCount={2} - columnCount={1} - rows={rows} - rowCount={rows.length} - rowRenderer={rowRenderer} - width={width} - role="grid" - /> - )} - -
- ); - } -} +```js file="./Actions.tsx" ``` ### Filterable with WindowScroller -```js -import React from 'react'; -import { - Button, - ButtonVariant, - Toolbar, - ToolbarItem, - ToolbarContent, - ToolbarFilter, - ToolbarToggleGroup, - ToolbarGroup, - InputGroup, - TextInput -} from '@patternfly/react-core'; -import { debounce } from '@patternfly/react-core'; -import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon'; -import FilterIcon from '@patternfly/react-icons/dist/esm/icons/filter-icon'; -import { ActionsColumn } from '@patternfly/react-table'; -import { Table as TableDeprecated, TableHeader as TableHeaderDeprecated } from '@patternfly/react-table/deprecated'; -import { - Dropdown, - DropdownItem, - DropdownPosition, - DropdownToggle, - Select, - SelectOption, - SelectVariant -} from '@patternfly/react-core/deprecated'; -import { CellMeasurerCache, CellMeasurer } from 'react-virtualized'; -import { AutoSizer, VirtualTableBody, WindowScroller } from '@patternfly/react-virtualized-extension'; - -class FilterExample extends React.Component { - constructor(props) { - super(props); - - this.actionsVirtualBody = null; - - const rows = []; - for (let i = 0; i < 100; i++) { - const data = {}; - if (i % 2 === 0) { - data.cells = [`US-Node ${i}`, i, i, 'Down', 'Brno']; - } else if (i % 3 === 0) { - data.cells = [`CN-Node ${i}`, i, i, 'Running', 'Westford']; - } else { - data.cells = [`US-Node ${i}`, i, i, 'Stopped', 'Raleigh']; - } - rows.push(data); - } - this.scrollableElement = React.createRef(); - - this.state = { - scrollableElement: null, - - filters: { - location: [], - name: [], - status: [] - }, - currentCategory: 'Name', - isFilterDropdownOpen: false, - isCategoryDropdownOpen: false, - nameInput: '', - columns: [ - { title: 'Servers' }, - { title: 'Threads' }, - { title: 'Applications' }, - { title: 'Status' }, - { title: 'Location' } - ], - rows, - inputValue: '', - actions: [ - { - title: 'Some action', - onClick: (event, rowId, rowData, extra) => console.log('clicked on Some action, on row: ', rowId) - }, - { - title:
Another action
, - onClick: (event, rowId, rowData, extra) => console.log('clicked on Another action, on row: ', rowId) - }, - { - isSeparator: true - }, - { - title: 'Third action', - onClick: (event, rowId, rowData, extra) => console.log('clicked on Third action, on row: ', rowId) - } - ] - }; - - this._handleResize = debounce(this._handleResize.bind(this), 100); - - this.onDelete = (type = '', id = '') => { - if (type) { - this.setState(prevState => { - prevState.filters[type.toLowerCase()] = prevState.filters[type.toLowerCase()].filter(s => s !== id); - return { - filters: prevState.filters - }; - }); - } else { - this.setState({ - filters: { - location: [], - name: [], - status: [] - }, - inputValue: '' - }); - } - }; - - this.onCategoryToggle = isOpen => { - this.setState({ - isCategoryDropdownOpen: isOpen - }); - }; - - this.onCategorySelect = event => { - this.setState({ - currentCategory: event.target.innerText, - isCategoryDropdownOpen: !this.state.isCategoryDropdownOpen - }); - }; - - this.onFilterToggle = isOpen => { - this.setState({ - isFilterDropdownOpen: isOpen - }); - }; - - this.onFilterSelect = event => { - this.setState({ - isFilterDropdownOpen: !this.state.isFilterDropdownOpen - }); - }; - - this.onInputChange = newValue => { - // this.setState({ inputValue: newValue }); - if (newValue === '') { - this.onDelete(); - this.setState({ - inputValue: newValue - }); - } else { - this.setState(prevState => { - return { - filters: { - ...prevState.filters, - ['name']: [newValue] - }, - inputValue: newValue - }; - }); - } - }; - - this.onRowSelect = (event, isSelected, rowId) => { - let rows; - if (rowId === -1) { - rows = this.state.rows.map(oneRow => { - oneRow.selected = isSelected; - return oneRow; - }); - } else { - rows = [...this.state.rows]; - rows[rowId].selected = isSelected; - } - this.setState({ - rows - }); - }; - - this.onStatusSelect = (event, selection) => { - const checked = event.target.checked; - this.setState(prevState => { - const prevSelections = prevState.filters['status']; - return { - filters: { - ...prevState.filters, - status: checked ? [...prevSelections, selection] : prevSelections.filter(value => value !== selection) - } - }; - }); - }; - - this.onNameInput = event => { - if (event.key && event.key !== 'Enter') { - return; - } - - const { inputValue } = this.state; - this.setState(prevState => { - const prevFilters = prevState.filters['name']; - return { - filters: { - ...prevState.filters, - ['name']: prevFilters.includes(inputValue) ? prevFilters : [...prevFilters, inputValue] - }, - inputValue: '' - }; - }); - }; - - this.onLocationSelect = (event, selection) => { - this.setState(prevState => { - return { - filters: { - ...prevState.filters, - ['location']: [selection] - } - }; - }); - this.onFilterSelect(); - }; - - this._handleResize = debounce(this._handleResize.bind(this), 100); - this._bindBodyRef = this._bindBodyRef.bind(this); - } - - componentDidMount() { - // re-render after resize - window.addEventListener('resize', this._handleResize); - - setTimeout(() => { - const scollableElement = document.getElementById('content-scrollable-1'); - this.setState({ scollableElement }); - }); - - // re-render after resize - window.addEventListener('resize', this._handleResize); - } - - componentWillUnmount() { - window.removeEventListener('resize', this._handleResize); - } - - _handleResize() { - this._cellMeasurementCache.clearAll(); - this._bodyRef.recomputeVirtualGridSize(); - } - - _bindBodyRef(ref) { - this._bodyRef = ref; - } - - buildCategoryDropdown() { - const { isCategoryDropdownOpen, currentCategory } = this.state; - - return ( - - - {currentCategory} - - } - isOpen={isCategoryDropdownOpen} - dropdownItems={[ - Location, - Name, - Status - ]} - style={{ width: '100%' }} - > - - ); - } - - buildFilterDropdown() { - const { currentCategory, isFilterDropdownOpen, inputValue, filters } = this.state; - - const locationMenuItems = [ - , - , - , - , - - ]; - - const statusMenuItems = [ - , - , - , - , - - ]; - - return ( - - - - - - - - - - - - - - - ); - } - - renderToolbar() { - const { filters } = this.state; - return ( - - - } breakpoint="xl"> - - {this.buildCategoryDropdown()} - {this.buildFilterDropdown()} - - - - - ); - } - - render() { - const { loading, rows, columns, actions, filters, scollableElement } = this.state; - - const filteredRows = - filters.name.length > 0 || filters.location.length > 0 || filters.status.length > 0 - ? rows.filter(row => { - return ( - (filters.name.length === 0 || - filters.name.some(name => row.cells[0].toLowerCase().includes(name.toLowerCase()))) && - (filters.location.length === 0 || filters.location.includes(row.cells[4])) && - (filters.status.length === 0 || filters.status.includes(row.cells[3])) - ); - }) - : rows; - const measurementCache = new CellMeasurerCache({ - fixedWidth: true, - minHeight: 44, - keyMapper: rowIndex => rowIndex - }); - - const rowRenderer = ({ index, isScrolling, key, style, parent }) => { - const { columns, actions } = this.state; - - return ( - - - {filteredRows[index].cells[0]} - {filteredRows[index].cells[1]} - {filteredRows[index].cells[2]} - {filteredRows[index].cells[3]} - {filteredRows[index].cells[4]} - - - - - - ); - }; - - return ( - - {this.renderToolbar()} - -
-
- {!loading && filteredRows.length > 0 && ( -
- - - - - {({ height, isScrolling, registerChild, onChildScroll, scrollTop }) => ( - - {({ width }) => ( -
- (this.actionsVirtualBody = ref)} - autoHeight - className="pf-v5-c-table pf-v5-c-virtualized pf-v5-c-window-scroller" - deferredMeasurementCache={measurementCache} - rowHeight={measurementCache.rowHeight} - height={height || 0} - overscanRowCount={10} - columnCount={6} - rows={filteredRows} - rowCount={filteredRows.length} - rowRenderer={rowRenderer} - scrollTop={scrollTop} - width={width} - role="grid" - /> -
- )} -
- )} -
-
- )} -
-
-
- ); - } -} +```js file="./FilterableWithWindowScroller.tsx" ``` diff --git a/packages/module/patternfly-docs/content/examples/WindowScroller.md b/packages/module/patternfly-docs/content/examples/WindowScroller.md index 605f974..dbfed96 100644 --- a/packages/module/patternfly-docs/content/examples/WindowScroller.md +++ b/packages/module/patternfly-docs/content/examples/WindowScroller.md @@ -22,295 +22,10 @@ import './WindowScroller.example.css'; ### Window scroller -```js -import React from 'react'; -import { debounce } from '@patternfly/react-core'; -import { TableGridBreakpoint } from '@patternfly/react-table'; -import { Table as TableDeprecated, TableHeader as TableHeaderDeprecated } from '@patternfly/react-table/deprecated'; -import { CellMeasurerCache, CellMeasurer } from 'react-virtualized'; -import { AutoSizer, VirtualTableBody, WindowScroller } from '@patternfly/react-virtualized-extension'; - -class WindowScrollerExample extends React.Component { - constructor(props) { - super(props); - const rows = []; - for (let i = 0; i < 100000; i++) { - const cells = []; - const num = Math.floor(Math.random() * Math.floor(2)) + 1; - for (let j = 0; j < 5; j++) { - const cellValue = i.toString() + ' Arma virumque cano Troiae qui primus ab oris. '.repeat(num); - cells.push(cellValue); - } - rows.push({ - id: `window-scroller-row-${i}`, - cells - }); - - this._cellMeasurementCache = new CellMeasurerCache({ - fixedWidth: true, - minHeight: 44, - keyMapper: rowIndex => rowIndex - }); - } - - this.state = { - scrollToIndex: -1, // can be used to programmatically set current index - scrollableElement: null, - columns: [ - { - title: 'Repositories', - props: { className: 'pf-m-6-col-on-sm pf-m-4-col-on-md pf-m-3-col-on-lg pf-m-2-col-on-xl' } - }, - { - title: 'Branches', - props: { className: 'pf-m-6-col-on-sm pf-m-4-col-on-md pf-m-3-col-on-lg pf-m-2-col-on-xl' } - }, - { - title: 'Pull requests', - props: { className: 'pf-m-4-col-on-md pf-m-4-col-on-lg pf-m-3-col-on-xl pf-m-hidden pf-m-visible-on-md' } - }, - { - title: 'Workspaces', - props: { className: 'pf-m-2-col-on-lg pf-m-2-col-on-xl pf-m-hidden pf-m-visible-on-lg' } - }, - { title: 'Last Commit', props: { className: 'pf-m-3-col-on-xl pf-m-hidden pf-m-visible-on-xl' } } - ], - rows - }; - - this._handleResize = debounce(this._handleResize.bind(this), 100); - this._bindBodyRef = this._bindBodyRef.bind(this); - } - - componentDidMount() { - // re-render after resize - window.addEventListener('resize', this._handleResize); - - this.setState({ scrollableElement: document.getElementById('content-scrollable-1') }); - } - - componentWillUnmount() { - window.removeEventListener('resize', this._handleResize); - } - - _handleResize() { - this._cellMeasurementCache.clearAll(); - this._bodyRef.recomputeVirtualGridSize(); - } - - _bindBodyRef(ref) { - this._bodyRef = ref; - } - - render() { - const { scrollToIndex, columns, rows, scrollableElement } = this.state; - - const rowRenderer = ({ index, isScrolling, key, style, parent }) => { - const { rows, columns } = this.state; - const text = rows[index].cells[0]; - - return ( - - - - {text} - - - {text} - - - {text} - - - {text} - - - {text} - - - - ); - }; - - return ( -
-
- - - - {scrollableElement && - {({ height, isScrolling, registerChild, onChildScroll, scrollTop }) => ( - - {({ width }) => ( -
- -
- )} -
- )} -
} -
-
- ); - } -} +```js file="./WindowScroller.tsx" ``` ### Using composable table components -```js -import React from 'react'; -import { CellMeasurerCache, CellMeasurer } from 'react-virtualized'; -import { AutoSizer, VirtualTableBody, WindowScroller } from '@patternfly/react-virtualized-extension'; -import { Table, Thead, Tr, Th, Td, Caption, TableGridBreakpoint } from '@patternfly/react-table'; - -ComposableTableWindowScroller = () => { - const [scrollableElement, setScrollableElement] = React.useState(); - React.useEffect(() => { - const scrollableElement = document.getElementById('content-scrollable-2'); - setScrollableElement(scrollableElement); - }); - const rows = []; - for (let i = 0; i < 100000; i++) { - const cells = []; - const num = Math.floor(Math.random() * Math.floor(2)) + 1; - for (let j = 0; j < 5; j++) { - const cellValue = i.toString() + ' Arma virumque cano Troiae qui primus ab oris. '.repeat(num); - cells.push(cellValue); - } - rows.push(cells); - } - const [selected, setSelected] = React.useState(rows.map(row => false)); - const columns = ['Repositories', 'Branches', 'Pull requests', 'Workspaces', 'Last Commit']; - const scrollToIndex = -1; // can be used to programmatically set current index - - const onSelect = (event, isSelected, rowId) => { - setSelected(selected.map((sel, index) => (index === rowId ? isSelected : sel))); - }; - - const measurementCache = new CellMeasurerCache({ - fixedWidth: true, - minHeight: 44, - keyMapper: rowIndex => rowIndex - }); - - const rowRenderer = ({ index: rowIndex, isScrolling, key, style, parent }) => { - const text = rows[rowIndex][0]; - - return ( - - - - {columns.map((col, index) => ( - {text} - ))} - - - ); - }; - - const scrollableContainerStyle = { - height: 500 /* important note: the scrollable container should have some sort of fixed height, or it should be wrapped in container that is smaller than ReactVirtualized__VirtualGrid container and has overflow visible if using the Window Scroller. See WindowScroller.example.css */, - overflowX: 'auto', - overflowY: 'scroll', - scrollBehavior: 'smooth', - WebkitOverflowScrolling: 'touch', - position: 'relative' - }; - - return ( -
- - - - - - ))} - - -
Virtualized table with composable table components
- {columns.map((col, index) => ( - {col}
- - {({ height, isScrolling, registerChild, onChildScroll, scrollTop }) => ( - - {({ width }) => ( -
- -
- )} -
- )} -
-
- ); -}; +```js file="UsingComposableTableComponentsDemo.tsx" ``` diff --git a/packages/module/patternfly-docs/content/examples/WindowScroller.tsx b/packages/module/patternfly-docs/content/examples/WindowScroller.tsx new file mode 100644 index 0000000..6383e39 --- /dev/null +++ b/packages/module/patternfly-docs/content/examples/WindowScroller.tsx @@ -0,0 +1,170 @@ +import React from 'react'; +import { debounce } from '@patternfly/react-core'; +import { TableGridBreakpoint } from '@patternfly/react-table'; +import { Table as TableDeprecated, TableHeader as TableHeaderDeprecated } from '@patternfly/react-table/deprecated'; +import { CellMeasurerCache, CellMeasurer } from 'react-virtualized'; +import { AutoSizer, VirtualTableBody, WindowScroller } from '@patternfly/react-virtualized-extension'; + +export class WindowScrollerExample extends React.Component { + constructor(props) { + super(props); + const rows = []; + for (let i = 0; i < 100000; i++) { + const cells = []; + const num = Math.floor(Math.random() * Math.floor(2)) + 1; + for (let j = 0; j < 5; j++) { + const cellValue = i.toString() + ' Arma virumque cano Troiae qui primus ab oris. '.repeat(num); + cells.push(cellValue); + } + rows.push({ + id: `window-scroller-row-${i}`, + cells + }); + + this._cellMeasurementCache = new CellMeasurerCache({ + fixedWidth: true, + minHeight: 44, + keyMapper: (rowIndex) => rowIndex + }); + } + + this.state = { + scrollToIndex: -1, // can be used to programmatically set current index + scrollableElement: null, + columns: [ + { + title: 'Repositories', + props: { className: 'pf-m-6-col-on-sm pf-m-4-col-on-md pf-m-3-col-on-lg pf-m-2-col-on-xl' } + }, + { + title: 'Branches', + props: { className: 'pf-m-6-col-on-sm pf-m-4-col-on-md pf-m-3-col-on-lg pf-m-2-col-on-xl' } + }, + { + title: 'Pull requests', + props: { className: 'pf-m-4-col-on-md pf-m-4-col-on-lg pf-m-3-col-on-xl pf-m-hidden pf-m-visible-on-md' } + }, + { + title: 'Workspaces', + props: { className: 'pf-m-2-col-on-lg pf-m-2-col-on-xl pf-m-hidden pf-m-visible-on-lg' } + }, + { title: 'Last Commit', props: { className: 'pf-m-3-col-on-xl pf-m-hidden pf-m-visible-on-xl' } } + ], + rows + }; + + this._handleResize = debounce(this._handleResize.bind(this), 100); + this._bindBodyRef = this._bindBodyRef.bind(this); + } + + componentDidMount() { + // re-render after resize + window.addEventListener('resize', this._handleResize); + + this.setState({ scrollableElement: document.getElementById('content-scrollable-1') }); + } + + componentWillUnmount() { + window.removeEventListener('resize', this._handleResize); + } + + _handleResize() { + this._cellMeasurementCache.clearAll(); + this._bodyRef.recomputeVirtualGridSize(); + } + + _bindBodyRef(ref) { + this._bodyRef = ref; + } + + render() { + const { scrollToIndex, columns, rows, scrollableElement } = this.state; + + const rowRenderer = ({ index, _isScrolling, key, style, parent }) => { + const { rows, columns } = this.state; + const text = rows[index].cells[0]; + + return ( + + + + {text} + + + {text} + + + {text} + + + {text} + + + {text} + + + + ); + }; + + return ( +
+
+ + + + {scrollableElement && ( + + {({ height, isScrolling, registerChild, onChildScroll, scrollTop }) => ( + + {({ width }) => ( +
+ +
+ )} +
+ )} +
+ )} +
+
+ ); + } +} diff --git a/packages/module/patternfly-docs/generated/extensions/virtual-scroll-table/react.js b/packages/module/patternfly-docs/generated/extensions/virtual-scroll-table/react.js index e00c243..3b6a220 100644 --- a/packages/module/patternfly-docs/generated/extensions/virtual-scroll-table/react.js +++ b/packages/module/patternfly-docs/generated/extensions/virtual-scroll-table/react.js @@ -6,13 +6,13 @@ import { CellMeasurerCache, CellMeasurer} from 'react-virtualized'; import { AutoSizer, VirtualTableBody, WindowScroller } from '@patternfly/react-virtualized-extension'; import { Table as TableDeprecated, TableHeader as TableHeaderDeprecated } from '@patternfly/react-table/deprecated'; import { - Dropdown, - DropdownItem, - DropdownPosition, - DropdownToggle, - Select, - SelectOption, - SelectVariant + Dropdown as DropdownDeprecated, + DropdownItem as DropdownItemDeprecated, + DropdownPosition as DropdownPositionDeprecated, + DropdownToggle as DropdownToggleDeprecated, + Select as SelectDeprecated, + SelectOption as SelectOptionDeprecated, + SelectVariant as SelectVariantDeprecated } from '@patternfly/react-core/deprecated'; import '../../../content/examples/./VirtualGrid.example.css'; const pageData = { @@ -191,40 +191,40 @@ pageData.liveContext = { WindowScroller, TableDeprecated, TableHeaderDeprecated, - Dropdown, - DropdownItem, - DropdownPosition, - DropdownToggle, - Select, - SelectOption, - SelectVariant + DropdownDeprecated, + DropdownItemDeprecated, + DropdownPositionDeprecated, + DropdownToggleDeprecated, + SelectDeprecated, + SelectOptionDeprecated, + SelectVariantDeprecated }; pageData.relativeImports = { }; pageData.examples = { 'Basic': props => - rowIndex\n });\n\n const rowRenderer = ({ index, isScrolling, key, style, parent }) => {\n const { rows, columns } = this.state;\n\n return (\n \n \n \n {rows[index].cells[0]}\n \n \n {rows[index].cells[1]}\n \n \n {rows[index].cells[2]}\n \n \n {rows[index].cells[3]}\n \n \n {rows[index].cells[4]}\n \n \n \n );\n };\n\n return (\n
\n \n \n \n \n {({ width }) => (\n \n )}\n \n
\n );\n }\n}","title":"Basic","lang":"js"}}> + rowIndex\n });\n\n const rowRenderer = ({ index, isScrolling, key, style, parent }) => {\n const { rows, columns } = this.state;\n\n return (\n \n \n \n {rows[index].cells[0]}\n \n \n {rows[index].cells[1]}\n \n \n {rows[index].cells[2]}\n \n \n {rows[index].cells[3]}\n \n \n {rows[index].cells[4]}\n \n \n \n );\n };\n\n return (\n
\n \n \n \n \n {({ width }) => (\n \n )}\n \n
\n );\n }\n}\n","title":"Basic","lang":"js"}}>
, 'Using composable table components': props => - {\n const rows = [];\n for (let i = 0; i < 100; i++) {\n rows.push([`one-${i}`, `two-${i}`, `three-${i}`, `four-${i}`, `five-${i}`]);\n }\n const [selected, setSelected] = React.useState(rows.map(row => false));\n const columns = [\n 'Repositories', 'Branches', 'Pull requests', 'Workspaces', 'Last Commit'\n ];\n\n const onSelect = (event, isSelected, rowId) => {\n setSelected(selected.map((sel, index) => (index === rowId ? isSelected : sel)));\n };\n\n const measurementCache = new CellMeasurerCache({\n fixedWidth: true,\n minHeight: 44,\n keyMapper: rowIndex => rowIndex\n });\n\n const rowRenderer = ({ index: rowIndex, isScrolling, key, style, parent }) => (\n \n \n \n {columns.map((col, index) => (\n \n {rows[rowIndex][index]}\n \n ))}\n \n \n );\n\n return (\n
\n \n \n \n \n \n ))}\n \n \n
Virtualized table with composable table components
\n {columns.map((col, index) => (\n \n {col}\n
\n \n {({ width }) => (\n \n )}\n \n
\n );\n};","title":"Using composable table components","lang":"js"}}> + {\n const rows = [];\n for (let i = 0; i < 100; i++) {\n rows.push([`one-${i}`, `two-${i}`, `three-${i}`, `four-${i}`, `five-${i}`]);\n }\n const [selected, setSelected] = React.useState(rows.map((row) => false));\n const columns = ['Repositories', 'Branches', 'Pull requests', 'Workspaces', 'Last Commit'];\n\n const onSelect = (event, isSelected, rowId) => {\n setSelected(selected.map((sel, index) => (index === rowId ? isSelected : sel)));\n };\n\n const measurementCache = new CellMeasurerCache({\n fixedWidth: true,\n minHeight: 44,\n keyMapper: (rowIndex) => rowIndex\n });\n\n const rowRenderer = ({ index: rowIndex, isScrolling, key, style, parent }) => (\n \n \n \n {columns.map((col, index) => (\n {rows[rowIndex][index]}\n ))}\n \n \n );\n\n return (\n
\n \n \n \n \n \n ))}\n \n \n
Virtualized table with composable table components
\n {columns.map((col, index) => (\n {col}
\n \n {({ width }) => (\n \n )}\n \n
\n );\n};\n","title":"Using composable table components","lang":"js"}}>
, 'Sortable': props => - \n a.cells[index] < b.cells[index] ? -1 : a.cells[index] > b.cells[index] ? 1 : 0\n );\n this.setState({\n sortBy: {\n index,\n direction\n },\n rows: direction === SortByDirection.asc ? sortedRows : sortedRows.reverse()\n });\n\n this.sortableVirtualBody.forceUpdateVirtualGrid();\n }\n\n render() {\n const { sortBy, columns, rows } = this.state;\n\n const measurementCache = new CellMeasurerCache({\n fixedWidth: true,\n minHeight: 44,\n keyMapper: rowIndex => rowIndex\n });\n\n const rowRenderer = ({ index, isScrolling, key, style, parent }) => {\n const { rows, columns } = this.state;\n\n return (\n \n \n \n {rows[index].cells[0]}\n \n \n {rows[index].cells[1]}\n \n \n {rows[index].cells[2]}\n \n \n {rows[index].cells[3]}\n \n \n {rows[index].cells[4]}\n \n \n \n );\n };\n\n return (\n
\n \n \n \n \n {({ width }) => (\n (this.sortableVirtualBody = ref)}\n className=\"pf-v5-c-table pf-v5-c-virtualized pf-v5-c-window-scroller\"\n deferredMeasurementCache={measurementCache}\n rowHeight={measurementCache.rowHeight}\n height={400}\n overscanRowCount={2}\n columnCount={1}\n rows={rows}\n rowCount={rows.length}\n rowRenderer={rowRenderer}\n width={width}\n role=\"grid\"\n />\n )}\n \n
\n );\n }\n}","title":"Sortable","lang":"js"}}> + \n a.cells[index] < b.cells[index] ? -1 : a.cells[index] > b.cells[index] ? 1 : 0\n );\n this.setState({\n sortBy: {\n index,\n direction\n },\n rows: direction === SortByDirection.asc ? sortedRows : sortedRows.reverse()\n });\n\n this.sortableVirtualBody.forceUpdateVirtualGrid();\n }\n\n render() {\n const { sortBy, columns, rows } = this.state;\n\n const measurementCache = new CellMeasurerCache({\n fixedWidth: true,\n minHeight: 44,\n keyMapper: (rowIndex) => rowIndex\n });\n\n const rowRenderer = ({ index, isScrolling, key, style, parent }) => {\n const { rows, columns } = this.state;\n\n return (\n \n \n \n {rows[index].cells[0]}\n \n \n {rows[index].cells[1]}\n \n \n {rows[index].cells[2]}\n \n \n {rows[index].cells[3]}\n \n \n {rows[index].cells[4]}\n \n \n \n );\n };\n\n return (\n
\n \n \n \n \n {({ width }) => (\n (this.sortableVirtualBody = ref)}\n className=\"pf-v5-c-table pf-v5-c-virtualized pf-v5-c-window-scroller\"\n deferredMeasurementCache={measurementCache}\n rowHeight={measurementCache.rowHeight}\n height={400}\n overscanRowCount={2}\n columnCount={1}\n rows={rows}\n rowCount={rows.length}\n rowRenderer={rowRenderer}\n width={width}\n role=\"grid\"\n />\n )}\n \n
\n );\n }\n}\n","title":"Sortable","lang":"js"}}>
, 'Selectable': props => - {\n oneRow.selected = isSelected;\n return oneRow;\n });\n } else {\n rows = [...this.state.rows];\n const rowIndex = rows.findIndex(r => r.id === rowData.id);\n rows[rowIndex] = { ...rows[rowIndex], selected: isSelected };\n }\n this.setState({\n rows\n });\n this.selectableVirtualBody.forceUpdateVirtualGrid();\n }\n\n render() {\n const { columns, rows } = this.state;\n\n const measurementCache = new CellMeasurerCache({\n fixedWidth: true,\n minHeight: 44,\n keyMapper: rowIndex => rowIndex\n });\n\n const rowRenderer = ({ index, isScrolling, key, style, parent }) => {\n const { rows, columns } = this.state;\n\n return (\n \n \n \n {\n this.onSelect(e, e.target.checked, 0, { id: rows[index].id });\n }}\n />\n \n \n {rows[index].cells[0]}\n \n \n {rows[index].cells[1]}\n \n \n {rows[index].cells[2]}\n \n \n {rows[index].cells[3]}\n \n \n \n );\n };\n\n return (\n
\n \n \n \n \n {({ width }) => (\n (this.selectableVirtualBody = ref)}\n className=\"pf-v5-c-table pf-v5-c-virtualized pf-v5-c-window-scroller\"\n deferredMeasurementCache={measurementCache}\n rowHeight={measurementCache.rowHeight}\n height={400}\n overscanRowCount={2}\n columnCount={1}\n rows={rows}\n rowCount={rows.length}\n rowRenderer={rowRenderer}\n width={width}\n role=\"grid\"\n />\n )}\n \n
\n );\n }\n}","title":"Selectable","lang":"js"}}> + {\n oneRow.selected = isSelected;\n return oneRow;\n });\n } else {\n rows = [...this.state.rows];\n const rowIndex = rows.findIndex((r) => r.id === rowData.id);\n rows[rowIndex] = { ...rows[rowIndex], selected: isSelected };\n }\n this.setState({\n rows\n });\n this.selectableVirtualBody.forceUpdateVirtualGrid();\n }\n\n render() {\n const { columns, rows } = this.state;\n\n const measurementCache = new CellMeasurerCache({\n fixedWidth: true,\n minHeight: 44,\n keyMapper: (rowIndex) => rowIndex\n });\n\n const rowRenderer = ({ index, isScrolling, key, style, parent }) => {\n const { rows, columns } = this.state;\n\n return (\n \n \n \n {\n this.onSelect(e, e.target.checked, 0, { id: rows[index].id });\n }}\n />\n \n \n {rows[index].cells[0]}\n \n \n {rows[index].cells[1]}\n \n \n {rows[index].cells[2]}\n \n \n {rows[index].cells[3]}\n \n \n \n );\n };\n\n return (\n
\n \n \n \n \n {({ width }) => (\n (this.selectableVirtualBody = ref)}\n className=\"pf-v5-c-table pf-v5-c-virtualized pf-v5-c-window-scroller\"\n deferredMeasurementCache={measurementCache}\n rowHeight={measurementCache.rowHeight}\n height={400}\n overscanRowCount={2}\n columnCount={1}\n rows={rows}\n rowCount={rows.length}\n rowRenderer={rowRenderer}\n width={width}\n role=\"grid\"\n />\n )}\n \n
\n );\n }\n}\n","title":"Selectable","lang":"js"}}>
, 'Actions': props => - console.log('clicked on Some action, on row: ', rowId)\n },\n {\n title:
Another action
,\n onClick: (event, rowId, rowData, extra) => console.log('clicked on Another action, on row: ', rowId)\n },\n {\n isSeparator: true\n },\n {\n title: 'Third action',\n onClick: (event, rowId, rowData, extra) => console.log('clicked on Third action, on row: ', rowId)\n }\n ]\n };\n\n this._handleResize = debounce(this._handleResize.bind(this), 100);\n }\n\n componentDidMount() {\n // re-render after resize\n window.addEventListener('resize', this._handleResize);\n }\n\n componentWillUnmount() {\n window.removeEventListener('resize', this._handleResize);\n }\n\n _handleResize() {\n this.forceUpdate();\n }\n\n render() {\n const { columns, rows } = this.state;\n\n const measurementCache = new CellMeasurerCache({\n fixedWidth: true,\n minHeight: 44,\n keyMapper: rowIndex => rowIndex\n });\n\n const rowRenderer = ({ index, isScrolling, key, style, parent }) => {\n const { rows, columns, actions } = this.state;\n\n return (\n \n \n \n {rows[index].cells[0]}\n \n \n {rows[index].cells[1]}\n \n \n {rows[index].cells[2]}\n \n \n {rows[index].cells[3]}\n \n \n {rows[index].cells[4]}\n \n \n \n \n \n \n );\n };\n\n return (\n
\n \n \n \n \n {({ width }) => (\n (this.actionsVirtualBody = ref)}\n className=\"pf-v5-c-table pf-v5-c-virtualized pf-v5-c-window-scroller\"\n deferredMeasurementCache={measurementCache}\n rowHeight={measurementCache.rowHeight}\n height={400}\n overscanRowCount={2}\n columnCount={1}\n rows={rows}\n rowCount={rows.length}\n rowRenderer={rowRenderer}\n width={width}\n role=\"grid\"\n />\n )}\n \n
\n );\n }\n}","title":"Actions","lang":"js"}}> + console.log('clicked on Some action, on row: ', rowId)\n },\n {\n title:
Another action
,\n onClick: (event, rowId, rowData, extra) => console.log('clicked on Another action, on row: ', rowId)\n },\n {\n isSeparator: true\n },\n {\n title: 'Third action',\n onClick: (event, rowId, rowData, extra) => console.log('clicked on Third action, on row: ', rowId)\n }\n ]\n };\n\n this._handleResize = debounce(this._handleResize.bind(this), 100);\n }\n\n componentDidMount() {\n // re-render after resize\n window.addEventListener('resize', this._handleResize);\n }\n\n componentWillUnmount() {\n window.removeEventListener('resize', this._handleResize);\n }\n\n _handleResize() {\n this.forceUpdate();\n }\n\n render() {\n const { columns, rows } = this.state;\n\n const measurementCache = new CellMeasurerCache({\n fixedWidth: true,\n minHeight: 44,\n keyMapper: (rowIndex) => rowIndex\n });\n\n const rowRenderer = ({ index, isScrolling, key, style, parent }) => {\n const { rows, columns, actions } = this.state;\n\n return (\n \n \n \n {rows[index].cells[0]}\n \n \n {rows[index].cells[1]}\n \n \n {rows[index].cells[2]}\n \n \n {rows[index].cells[3]}\n \n \n {rows[index].cells[4]}\n \n \n \n \n \n \n );\n };\n\n return (\n
\n \n \n \n \n {({ width }) => (\n (this.actionsVirtualBody = ref)}\n className=\"pf-v5-c-table pf-v5-c-virtualized pf-v5-c-window-scroller\"\n deferredMeasurementCache={measurementCache}\n rowHeight={measurementCache.rowHeight}\n height={400}\n overscanRowCount={2}\n columnCount={1}\n rows={rows}\n rowCount={rows.length}\n rowRenderer={rowRenderer}\n width={width}\n role=\"grid\"\n />\n )}\n \n
\n );\n }\n}\n","title":"Actions","lang":"js"}}>
, 'Filterable with WindowScroller': props => - console.log('clicked on Some action, on row: ', rowId)\n },\n {\n title:
Another action
,\n onClick: (event, rowId, rowData, extra) => console.log('clicked on Another action, on row: ', rowId)\n },\n {\n isSeparator: true\n },\n {\n title: 'Third action',\n onClick: (event, rowId, rowData, extra) => console.log('clicked on Third action, on row: ', rowId)\n }\n ]\n };\n\n this._handleResize = debounce(this._handleResize.bind(this), 100);\n\n this.onDelete = (type = '', id = '') => {\n if (type) {\n this.setState(prevState => {\n prevState.filters[type.toLowerCase()] = prevState.filters[type.toLowerCase()].filter(s => s !== id);\n return {\n filters: prevState.filters\n };\n });\n } else {\n this.setState({\n filters: {\n location: [],\n name: [],\n status: []\n },\n inputValue: ''\n });\n }\n };\n\n this.onCategoryToggle = isOpen => {\n this.setState({\n isCategoryDropdownOpen: isOpen\n });\n };\n\n this.onCategorySelect = event => {\n this.setState({\n currentCategory: event.target.innerText,\n isCategoryDropdownOpen: !this.state.isCategoryDropdownOpen\n });\n };\n\n this.onFilterToggle = isOpen => {\n this.setState({\n isFilterDropdownOpen: isOpen\n });\n };\n\n this.onFilterSelect = event => {\n this.setState({\n isFilterDropdownOpen: !this.state.isFilterDropdownOpen\n });\n };\n\n this.onInputChange = newValue => {\n // this.setState({ inputValue: newValue });\n if (newValue === '') {\n this.onDelete();\n this.setState({\n inputValue: newValue\n });\n } else {\n this.setState(prevState => {\n return {\n filters: {\n ...prevState.filters,\n ['name']: [newValue]\n },\n inputValue: newValue\n };\n });\n }\n };\n\n this.onRowSelect = (event, isSelected, rowId) => {\n let rows;\n if (rowId === -1) {\n rows = this.state.rows.map(oneRow => {\n oneRow.selected = isSelected;\n return oneRow;\n });\n } else {\n rows = [...this.state.rows];\n rows[rowId].selected = isSelected;\n }\n this.setState({\n rows\n });\n };\n\n this.onStatusSelect = (event, selection) => {\n const checked = event.target.checked;\n this.setState(prevState => {\n const prevSelections = prevState.filters['status'];\n return {\n filters: {\n ...prevState.filters,\n status: checked ? [...prevSelections, selection] : prevSelections.filter(value => value !== selection)\n }\n };\n });\n };\n\n this.onNameInput = event => {\n if (event.key && event.key !== 'Enter') {\n return;\n }\n\n const { inputValue } = this.state;\n this.setState(prevState => {\n const prevFilters = prevState.filters['name'];\n return {\n filters: {\n ...prevState.filters,\n ['name']: prevFilters.includes(inputValue) ? prevFilters : [...prevFilters, inputValue]\n },\n inputValue: ''\n };\n });\n };\n\n this.onLocationSelect = (event, selection) => {\n this.setState(prevState => {\n return {\n filters: {\n ...prevState.filters,\n ['location']: [selection]\n }\n };\n });\n this.onFilterSelect();\n };\n\n this._handleResize = debounce(this._handleResize.bind(this), 100);\n this._bindBodyRef = this._bindBodyRef.bind(this);\n }\n\n componentDidMount() {\n // re-render after resize\n window.addEventListener('resize', this._handleResize);\n\n setTimeout(() => {\n const scollableElement = document.getElementById('content-scrollable-1');\n this.setState({ scollableElement });\n });\n\n // re-render after resize\n window.addEventListener('resize', this._handleResize);\n }\n\n componentWillUnmount() {\n window.removeEventListener('resize', this._handleResize);\n }\n\n _handleResize() {\n this._cellMeasurementCache.clearAll();\n this._bodyRef.recomputeVirtualGridSize();\n }\n\n _bindBodyRef(ref) {\n this._bodyRef = ref;\n }\n\n buildCategoryDropdown() {\n const { isCategoryDropdownOpen, currentCategory } = this.state;\n\n return (\n \n \n {currentCategory}\n \n }\n isOpen={isCategoryDropdownOpen}\n dropdownItems={[\n Location,\n Name,\n Status\n ]}\n style={{ width: '100%' }}\n >\n \n );\n }\n\n buildFilterDropdown() {\n const { currentCategory, isFilterDropdownOpen, inputValue, filters } = this.state;\n\n const locationMenuItems = [\n ,\n ,\n ,\n ,\n \n ];\n\n const statusMenuItems = [\n ,\n ,\n ,\n ,\n \n ];\n\n return (\n \n \n \n {locationMenuItems}\n \n \n \n \n \n \n \n \n \n \n \n \n {statusMenuItems}\n \n \n \n );\n }\n\n renderToolbar() {\n const { filters } = this.state;\n return (\n \n \n } breakpoint=\"xl\">\n \n {this.buildCategoryDropdown()}\n {this.buildFilterDropdown()}\n \n \n \n \n );\n }\n\n render() {\n const { loading, rows, columns, actions, filters, scollableElement } = this.state;\n\n const filteredRows =\n filters.name.length > 0 || filters.location.length > 0 || filters.status.length > 0\n ? rows.filter(row => {\n return (\n (filters.name.length === 0 ||\n filters.name.some(name => row.cells[0].toLowerCase().includes(name.toLowerCase()))) &&\n (filters.location.length === 0 || filters.location.includes(row.cells[4])) &&\n (filters.status.length === 0 || filters.status.includes(row.cells[3]))\n );\n })\n : rows;\n const measurementCache = new CellMeasurerCache({\n fixedWidth: true,\n minHeight: 44,\n keyMapper: rowIndex => rowIndex\n });\n\n const rowRenderer = ({ index, isScrolling, key, style, parent }) => {\n const { columns, actions } = this.state;\n\n return (\n \n \n {filteredRows[index].cells[0]}\n {filteredRows[index].cells[1]}\n {filteredRows[index].cells[2]}\n {filteredRows[index].cells[3]}\n {filteredRows[index].cells[4]}\n \n \n \n \n \n );\n };\n\n return (\n \n {this.renderToolbar()}\n\n \n
\n {!loading && filteredRows.length > 0 && (\n \n \n \n \n \n {({ height, isScrolling, registerChild, onChildScroll, scrollTop }) => (\n \n {({ width }) => (\n
\n (this.actionsVirtualBody = ref)}\n autoHeight\n className=\"pf-v5-c-table pf-v5-c-virtualized pf-v5-c-window-scroller\"\n deferredMeasurementCache={measurementCache}\n rowHeight={measurementCache.rowHeight}\n height={height || 0}\n overscanRowCount={10}\n columnCount={6}\n rows={filteredRows}\n rowCount={filteredRows.length}\n rowRenderer={rowRenderer}\n scrollTop={scrollTop}\n width={width}\n role=\"grid\"\n />\n
\n )}\n
\n )}\n
\n
\n )}\n \n \n
\n );\n }\n}","title":"Filterable with WindowScroller","lang":"js"}}> + console.log('clicked on Some action, on row: ', rowId)\n },\n {\n title:
Another action
,\n onClick: (event, rowId, rowData, extra) => console.log('clicked on Another action, on row: ', rowId)\n },\n {\n isSeparator: true\n },\n {\n title: 'Third action',\n onClick: (event, rowId, rowData, extra) => console.log('clicked on Third action, on row: ', rowId)\n }\n ]\n };\n\n this._handleResize = debounce(this._handleResize.bind(this), 100);\n\n this.onDelete = (type = '', id = '') => {\n if (type) {\n this.setState((prevState) => {\n prevState.filters[type.toLowerCase()] = prevState.filters[type.toLowerCase()].filter((s) => s !== id);\n return {\n filters: prevState.filters\n };\n });\n } else {\n this.setState({\n filters: {\n location: [],\n name: [],\n status: []\n },\n inputValue: ''\n });\n }\n };\n\n this.onCategoryToggle = (_event, isOpen) => {\n this.setState({\n isCategoryDropdownOpen: isOpen\n });\n };\n\n this.onCategorySelect = (event) => {\n this.setState({\n currentCategory: event.target.innerText,\n isCategoryDropdownOpen: !this.state.isCategoryDropdownOpen\n });\n };\n\n this.onFilterToggle = (_event, isOpen) => {\n this.setState({\n isFilterDropdownOpen: isOpen\n });\n };\n\n this.onFilterSelect = (event) => {\n this.setState({\n isFilterDropdownOpen: !this.state.isFilterDropdownOpen\n });\n };\n\n this.onInputChange = (_event, newValue) => {\n // this.setState({ inputValue: newValue });\n if (newValue === '') {\n this.onDelete();\n this.setState({\n inputValue: newValue\n });\n } else {\n this.setState((prevState) => {\n return {\n filters: {\n ...prevState.filters,\n ['name']: [newValue]\n },\n inputValue: newValue\n };\n });\n }\n };\n\n this.onRowSelect = (event, isSelected, rowId) => {\n let rows;\n if (rowId === -1) {\n rows = this.state.rows.map((oneRow) => {\n oneRow.selected = isSelected;\n return oneRow;\n });\n } else {\n rows = [...this.state.rows];\n rows[rowId].selected = isSelected;\n }\n this.setState({\n rows\n });\n };\n\n this.onStatusSelect = (event, selection) => {\n const checked = event.target.checked;\n this.setState((prevState) => {\n const prevSelections = prevState.filters['status'];\n return {\n filters: {\n ...prevState.filters,\n status: checked ? [...prevSelections, selection] : prevSelections.filter((value) => value !== selection)\n }\n };\n });\n };\n\n this.onNameInput = (event) => {\n if (event.key && event.key !== 'Enter') {\n return;\n }\n\n const { inputValue } = this.state;\n this.setState((prevState) => {\n const prevFilters = prevState.filters['name'];\n return {\n filters: {\n ...prevState.filters,\n ['name']: prevFilters.includes(inputValue) ? prevFilters : [...prevFilters, inputValue]\n },\n inputValue: ''\n };\n });\n };\n\n this.onLocationSelect = (event, selection) => {\n this.setState((prevState) => {\n return {\n filters: {\n ...prevState.filters,\n ['location']: [selection]\n }\n };\n });\n this.onFilterSelect();\n };\n\n this._handleResize = debounce(this._handleResize.bind(this), 100);\n this._bindBodyRef = this._bindBodyRef.bind(this);\n }\n\n componentDidMount() {\n // re-render after resize\n window.addEventListener('resize', this._handleResize);\n\n setTimeout(() => {\n const scollableElement = document.getElementById('content-scrollable-1');\n this.setState({ scollableElement });\n });\n\n // re-render after resize\n window.addEventListener('resize', this._handleResize);\n }\n\n componentWillUnmount() {\n window.removeEventListener('resize', this._handleResize);\n }\n\n _handleResize() {\n this._cellMeasurementCache.clearAll();\n this._bodyRef.recomputeVirtualGridSize();\n }\n\n _bindBodyRef(ref) {\n this._bodyRef = ref;\n }\n\n buildCategoryDropdown() {\n const { isCategoryDropdownOpen, currentCategory } = this.state;\n\n return (\n \n \n {currentCategory}\n \n }\n isOpen={isCategoryDropdownOpen}\n dropdownItems={[\n Location,\n Name,\n Status\n ]}\n style={{ width: '100%' }}\n >\n \n );\n }\n\n buildFilterDropdown() {\n const { currentCategory, isFilterDropdownOpen, inputValue, filters } = this.state;\n\n const locationMenuItems = [\n ,\n ,\n ,\n ,\n \n ];\n\n const statusMenuItems = [\n ,\n ,\n ,\n ,\n \n ];\n\n return (\n \n \n \n {locationMenuItems}\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n {statusMenuItems}\n \n \n \n );\n }\n\n renderToolbar() {\n const { filters } = this.state;\n return (\n \n \n } breakpoint=\"xl\">\n \n {this.buildCategoryDropdown()}\n {this.buildFilterDropdown()}\n \n \n \n \n );\n }\n\n render() {\n const { loading, rows, columns, actions, filters, scollableElement } = this.state;\n\n const filteredRows =\n filters.name.length > 0 || filters.location.length > 0 || filters.status.length > 0\n ? rows.filter((row) => {\n return (\n (filters.name.length === 0 ||\n filters.name.some((name) => row.cells[0].toLowerCase().includes(name.toLowerCase()))) &&\n (filters.location.length === 0 || filters.location.includes(row.cells[4])) &&\n (filters.status.length === 0 || filters.status.includes(row.cells[3]))\n );\n })\n : rows;\n const measurementCache = new CellMeasurerCache({\n fixedWidth: true,\n minHeight: 44,\n keyMapper: (rowIndex) => rowIndex\n });\n\n const rowRenderer = ({ index, isScrolling, key, style, parent }) => {\n const { columns, actions } = this.state;\n\n return (\n \n \n {filteredRows[index].cells[0]}\n {filteredRows[index].cells[1]}\n {filteredRows[index].cells[2]}\n {filteredRows[index].cells[3]}\n {filteredRows[index].cells[4]}\n \n \n \n \n \n );\n };\n\n return (\n \n {this.renderToolbar()}\n\n \n
\n {!loading && filteredRows.length > 0 && (\n
\n \n \n \n \n {({ height, isScrolling, registerChild, onChildScroll, scrollTop }) => (\n \n {({ width }) => (\n
\n (this.actionsVirtualBody = ref)}\n autoHeight\n className=\"pf-v5-c-table pf-v5-c-virtualized pf-v5-c-window-scroller\"\n deferredMeasurementCache={measurementCache}\n rowHeight={measurementCache.rowHeight}\n height={height || 0}\n overscanRowCount={10}\n columnCount={6}\n rows={filteredRows}\n rowCount={filteredRows.length}\n rowRenderer={rowRenderer}\n scrollTop={scrollTop}\n width={width}\n role=\"grid\"\n />\n
\n )}\n
\n )}\n
\n
\n )}\n
\n \n
\n );\n }\n}\n","title":"Filterable with WindowScroller","lang":"js"}}>
}; diff --git a/packages/module/patternfly-docs/generated/extensions/virtual-scroll-window-scroller/react.js b/packages/module/patternfly-docs/generated/extensions/virtual-scroll-window-scroller/react.js index d209a36..8b338e7 100644 --- a/packages/module/patternfly-docs/generated/extensions/virtual-scroll-window-scroller/react.js +++ b/packages/module/patternfly-docs/generated/extensions/virtual-scroll-window-scroller/react.js @@ -181,11 +181,11 @@ pageData.relativeImports = { }; pageData.examples = { 'Window scroller': props => - rowIndex\n });\n }\n\n this.state = {\n scrollToIndex: -1, // can be used to programmatically set current index\n scrollableElement: null,\n columns: [\n {\n title: 'Repositories',\n props: { className: 'pf-m-6-col-on-sm pf-m-4-col-on-md pf-m-3-col-on-lg pf-m-2-col-on-xl' }\n },\n {\n title: 'Branches',\n props: { className: 'pf-m-6-col-on-sm pf-m-4-col-on-md pf-m-3-col-on-lg pf-m-2-col-on-xl' }\n },\n {\n title: 'Pull requests',\n props: { className: 'pf-m-4-col-on-md pf-m-4-col-on-lg pf-m-3-col-on-xl pf-m-hidden pf-m-visible-on-md' }\n },\n {\n title: 'Workspaces',\n props: { className: 'pf-m-2-col-on-lg pf-m-2-col-on-xl pf-m-hidden pf-m-visible-on-lg' }\n },\n { title: 'Last Commit', props: { className: 'pf-m-3-col-on-xl pf-m-hidden pf-m-visible-on-xl' } }\n ],\n rows\n };\n\n this._handleResize = debounce(this._handleResize.bind(this), 100);\n this._bindBodyRef = this._bindBodyRef.bind(this);\n }\n\n componentDidMount() {\n // re-render after resize\n window.addEventListener('resize', this._handleResize);\n\n this.setState({ scrollableElement: document.getElementById('content-scrollable-1') });\n }\n\n componentWillUnmount() {\n window.removeEventListener('resize', this._handleResize);\n }\n\n _handleResize() {\n this._cellMeasurementCache.clearAll();\n this._bodyRef.recomputeVirtualGridSize();\n }\n\n _bindBodyRef(ref) {\n this._bodyRef = ref;\n }\n\n render() {\n const { scrollToIndex, columns, rows, scrollableElement } = this.state;\n\n const rowRenderer = ({ index, isScrolling, key, style, parent }) => {\n const { rows, columns } = this.state;\n const text = rows[index].cells[0];\n\n return (\n \n \n \n {text}\n \n \n {text}\n \n \n {text}\n \n \n {text}\n \n \n {text}\n \n \n \n );\n };\n\n return (\n \n
\n \n \n \n {scrollableElement && \n {({ height, isScrolling, registerChild, onChildScroll, scrollTop }) => (\n \n {({ width }) => (\n
\n \n
\n )}\n
\n )}\n
}\n
\n \n );\n }\n}","title":"Window scroller","lang":"js"}}> + rowIndex\n });\n }\n\n this.state = {\n scrollToIndex: -1, // can be used to programmatically set current index\n scrollableElement: null,\n columns: [\n {\n title: 'Repositories',\n props: { className: 'pf-m-6-col-on-sm pf-m-4-col-on-md pf-m-3-col-on-lg pf-m-2-col-on-xl' }\n },\n {\n title: 'Branches',\n props: { className: 'pf-m-6-col-on-sm pf-m-4-col-on-md pf-m-3-col-on-lg pf-m-2-col-on-xl' }\n },\n {\n title: 'Pull requests',\n props: { className: 'pf-m-4-col-on-md pf-m-4-col-on-lg pf-m-3-col-on-xl pf-m-hidden pf-m-visible-on-md' }\n },\n {\n title: 'Workspaces',\n props: { className: 'pf-m-2-col-on-lg pf-m-2-col-on-xl pf-m-hidden pf-m-visible-on-lg' }\n },\n { title: 'Last Commit', props: { className: 'pf-m-3-col-on-xl pf-m-hidden pf-m-visible-on-xl' } }\n ],\n rows\n };\n\n this._handleResize = debounce(this._handleResize.bind(this), 100);\n this._bindBodyRef = this._bindBodyRef.bind(this);\n }\n\n componentDidMount() {\n // re-render after resize\n window.addEventListener('resize', this._handleResize);\n\n this.setState({ scrollableElement: document.getElementById('content-scrollable-1') });\n }\n\n componentWillUnmount() {\n window.removeEventListener('resize', this._handleResize);\n }\n\n _handleResize() {\n this._cellMeasurementCache.clearAll();\n this._bodyRef.recomputeVirtualGridSize();\n }\n\n _bindBodyRef(ref) {\n this._bodyRef = ref;\n }\n\n render() {\n const { scrollToIndex, columns, rows, scrollableElement } = this.state;\n\n const rowRenderer = ({ index, isScrolling, key, style, parent }) => {\n const { rows, columns } = this.state;\n const text = rows[index].cells[0];\n\n return (\n \n \n \n {text}\n \n \n {text}\n \n \n {text}\n \n \n {text}\n \n \n {text}\n \n \n \n );\n };\n\n return (\n \n
\n \n \n \n {scrollableElement && (\n \n {({ height, isScrolling, registerChild, onChildScroll, scrollTop }) => (\n \n {({ width }) => (\n
\n \n
\n )}\n
\n )}\n
\n )}\n
\n \n );\n }\n}\n","title":"Window scroller","lang":"js"}}>
, 'Using composable table components': props => - {\n const [scrollableElement, setScrollableElement] = React.useState();\n React.useEffect(() => {\n const scrollableElement = document.getElementById('content-scrollable-2');\n setScrollableElement(scrollableElement);\n });\n const rows = [];\n for (let i = 0; i < 100000; i++) {\n const cells = [];\n const num = Math.floor(Math.random() * Math.floor(2)) + 1;\n for (let j = 0; j < 5; j++) {\n const cellValue = i.toString() + ' Arma virumque cano Troiae qui primus ab oris. '.repeat(num);\n cells.push(cellValue);\n }\n rows.push(cells);\n }\n const [selected, setSelected] = React.useState(rows.map(row => false));\n const columns = ['Repositories', 'Branches', 'Pull requests', 'Workspaces', 'Last Commit'];\n const scrollToIndex = -1; // can be used to programmatically set current index\n\n const onSelect = (event, isSelected, rowId) => {\n setSelected(selected.map((sel, index) => (index === rowId ? isSelected : sel)));\n };\n\n const measurementCache = new CellMeasurerCache({\n fixedWidth: true,\n minHeight: 44,\n keyMapper: rowIndex => rowIndex\n });\n\n const rowRenderer = ({ index: rowIndex, isScrolling, key, style, parent }) => {\n const text = rows[rowIndex][0];\n\n return (\n \n \n \n {columns.map((col, index) => (\n {text}\n ))}\n \n \n );\n };\n\n const scrollableContainerStyle = {\n height: 500 /* important note: the scrollable container should have some sort of fixed height, or it should be wrapped in container that is smaller than ReactVirtualized__VirtualGrid container and has overflow visible if using the Window Scroller. See WindowScroller.example.css */,\n overflowX: 'auto',\n overflowY: 'scroll',\n scrollBehavior: 'smooth',\n WebkitOverflowScrolling: 'touch',\n position: 'relative'\n };\n\n return (\n \n \n \n \n \n \n ))}\n \n \n
Virtualized table with composable table components
\n {columns.map((col, index) => (\n {col}
\n \n {({ height, isScrolling, registerChild, onChildScroll, scrollTop }) => (\n \n {({ width }) => (\n
\n \n
\n )}\n
\n )}\n
\n \n );\n};","title":"Using composable table components","lang":"js"}}> + {\n const [scrollableElement, setScrollableElement] = React.useState();\n React.useEffect(() => {\n const scrollableElement = document.getElementById('content-scrollable-2');\n setScrollableElement(scrollableElement);\n });\n const rows = [];\n for (let i = 0; i < 100000; i++) {\n const cells = [];\n const num = Math.floor(Math.random() * Math.floor(2)) + 1;\n for (let j = 0; j < 5; j++) {\n const cellValue = i.toString() + ' Arma virumque cano Troiae qui primus ab oris. '.repeat(num);\n cells.push(cellValue);\n }\n rows.push(cells);\n }\n const [selected, setSelected] = React.useState(rows.map((row) => false));\n const columns = ['Repositories', 'Branches', 'Pull requests', 'Workspaces', 'Last Commit'];\n const scrollToIndex = -1; // can be used to programmatically set current index\n\n const onSelect = (event, isSelected, rowId) => {\n setSelected(selected.map((sel, index) => (index === rowId ? isSelected : sel)));\n };\n\n const measurementCache = new CellMeasurerCache({\n fixedWidth: true,\n minHeight: 44,\n keyMapper: (rowIndex) => rowIndex\n });\n\n const rowRenderer = ({ index: rowIndex, isScrolling, key, style, parent }) => {\n const text = rows[rowIndex][0];\n\n return (\n \n \n \n {columns.map((col, index) => (\n {text}\n ))}\n \n \n );\n };\n\n const scrollableContainerStyle = {\n height: 500 /* important note: the scrollable container should have some sort of fixed height, or it should be wrapped in container that is smaller than ReactVirtualized__VirtualGrid container and has overflow visible if using the Window Scroller. See WindowScroller.example.css */,\n overflowX: 'auto',\n overflowY: 'scroll',\n scrollBehavior: 'smooth',\n WebkitOverflowScrolling: 'touch',\n position: 'relative'\n };\n\n return (\n \n \n \n \n \n \n ))}\n \n \n
Virtualized table with composable table components
\n {columns.map((col, index) => (\n {col}
\n \n {({ height, isScrolling, registerChild, onChildScroll, scrollTop }) => (\n \n {({ width }) => (\n
\n \n
\n )}\n
\n )}\n
\n \n );\n};\n","title":"Using composable table components","lang":"js"}}>
}; diff --git a/packages/module/release.config.js b/packages/module/release.config.js index 1fcafbb..0c2fbff 100644 --- a/packages/module/release.config.js +++ b/packages/module/release.config.js @@ -6,7 +6,16 @@ module.exports = { preset: 'angular' }, plugins: [ - '@semantic-release/commit-analyzer', + [ + '@semantic-release/commit-analyzer', + { + preset: 'angular', + releaseRules: [ + { type: 'chore', scope: 'deps', release: 'patch' }, + { type: 'chore', scope: 'ci-release', release: 'patch' } + ] + } + ], '@semantic-release/release-notes-generator', '@semantic-release/github', '@semantic-release/npm' diff --git a/yarn.lock b/yarn.lock index 15545b1..225788b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2081,10 +2081,10 @@ acorn-static-class-features "^1.0.0" astring "^1.7.5" -"@patternfly/documentation-framework@^2.0.0-alpha.69": - version "2.0.0-alpha.69" - resolved "https://registry.yarnpkg.com/@patternfly/documentation-framework/-/documentation-framework-2.0.0-alpha.69.tgz#be46270b8fa8724457fd5efe8cb689f34939c59e" - integrity sha512-hwmPsjlnINnYoXbsm7cw+B2l0R2ONIwLBEArDpXia93UjD7Iztnq+fGoKu/RU3wBOhplD+mOO5SeEFG48Z8X+g== +"@patternfly/documentation-framework@^5.0.15": + version "5.0.15" + resolved "https://registry.yarnpkg.com/@patternfly/documentation-framework/-/documentation-framework-5.0.15.tgz#56e6608de10a95a92787686e5db1eb3ff7c09b89" + integrity sha512-3r9fqPeAKY8GeJM6m7VPyPsiggxhyDbbWTo2/4T4NoNisVPpFXi0AzUaTpvJU2KcBx5pSot1mb84V3f8DHzWXg== dependencies: "@babel/core" "7.18.2" "@babel/plugin-proposal-class-properties" "7.17.12" @@ -2170,60 +2170,60 @@ puppeteer-cluster "^0.23.0" xmldoc "^1.1.2" -"@patternfly/patternfly@^5.0.0-prerelease.10": - version "5.0.0-prerelease.10" - resolved "https://registry.yarnpkg.com/@patternfly/patternfly/-/patternfly-5.0.0-prerelease.10.tgz#b5993d04be650f5103edb431436695c7c23c03cc" - integrity sha512-jVAqCl2UHiB4246fzLBNTcrY6iwllZ5V14KV4kN4/PIPGb3lgM7jpFxWSISsT6yApsVQ8mQngiWhwfqpDZpVaw== +"@patternfly/patternfly@^5.0.0-prerelease.16": + version "5.0.0-prerelease.16" + resolved "https://registry.yarnpkg.com/@patternfly/patternfly/-/patternfly-5.0.0-prerelease.16.tgz#63064971002b9b9b2f161bd8c2907cab55bbbebc" + integrity sha512-h5vNqRD9UMJO7ABX7vA3YJNMcsJwA+YUOuiEwcvnokHjv0g6kYNlTvYqIRJDab9wKpscbGmRSYyDgHYZvGO6hg== -"@patternfly/react-code-editor@^5.0.0-prerelease.13": - version "5.0.0-prerelease.13" - resolved "https://registry.yarnpkg.com/@patternfly/react-code-editor/-/react-code-editor-5.0.0-prerelease.13.tgz#72db62e6edd6e15014564e9064ff65e1c5fa638f" - integrity sha512-gbD7R+0oOxG/Af3FW5VILTUnTgSI+9XR2XO0x4RTUPCD4C0fvbU6VyBymdCJo7ukmqIVwJt8KsElL1pT/sClEg== +"@patternfly/react-code-editor@^5.0.0-prerelease.26": + version "5.0.0-prerelease.26" + resolved "https://registry.yarnpkg.com/@patternfly/react-code-editor/-/react-code-editor-5.0.0-prerelease.26.tgz#1cb4a73feaec6bf2b3b05697e230d47ab14f896e" + integrity sha512-Ml8wvkmdRUUZgfQP5TIyeN87DtW7jhLjuDnAYs9fDY/TGvyf+UjIJ3Bd+QqhVQCfbtZTvoXvy7woiTPMcF4DHg== dependencies: - "@patternfly/react-core" "^5.0.0-prerelease.13" - "@patternfly/react-icons" "^5.0.0-prerelease.7" - "@patternfly/react-styles" "^5.0.0-prerelease.5" + "@patternfly/react-core" "^5.0.0-prerelease.26" + "@patternfly/react-icons" "^5.0.0-prerelease.9" + "@patternfly/react-styles" "^5.0.0-prerelease.7" react-dropzone "14.2.3" tslib "^2.5.0" -"@patternfly/react-core@^5.0.0-prerelease.13": - version "5.0.0-prerelease.13" - resolved "https://registry.yarnpkg.com/@patternfly/react-core/-/react-core-5.0.0-prerelease.13.tgz#878b9d27b639bb870e79c6c388fcf617e3793641" - integrity sha512-NhZmaagCjEDhfOI0VPG5oeYeQkzUAUZB/gDg8VSDvs+2jnwrqRH/Wk+Sot9ix9GaU7Xad3jdkEY9HAqKomVsnw== +"@patternfly/react-core@^5.0.0-prerelease.26": + version "5.0.0-prerelease.26" + resolved "https://registry.yarnpkg.com/@patternfly/react-core/-/react-core-5.0.0-prerelease.26.tgz#208c3c95ba033c8a1ce11175216f4ad46d609eb5" + integrity sha512-oV8Ev5R0ktMI7gJFZ7XUSsGhjk88l1XSgNvleMwBqclYaqp+PgHsMCvJc9nhOUPmNjtPVZ5KjOgKAIs2UZrTog== dependencies: - "@patternfly/react-icons" "^5.0.0-prerelease.7" - "@patternfly/react-styles" "^5.0.0-prerelease.5" - "@patternfly/react-tokens" "^5.0.0-prerelease.5" + "@patternfly/react-icons" "^5.0.0-prerelease.9" + "@patternfly/react-styles" "^5.0.0-prerelease.7" + "@patternfly/react-tokens" "^5.0.0-prerelease.9" focus-trap "7.4.3" react-dropzone "^14.2.3" tslib "^2.5.0" -"@patternfly/react-icons@^ 5.0.0-prerelease.7", "@patternfly/react-icons@^5.0.0-prerelease.7": +"@patternfly/react-icons@^5.0.0-prerelease.9": + version "5.0.0-prerelease.9" + resolved "https://registry.yarnpkg.com/@patternfly/react-icons/-/react-icons-5.0.0-prerelease.9.tgz#0ccdffde7ad7c9712bae158d6c09326831a3ebc0" + integrity sha512-/+g45rml+GpI9UvIlacPLeZvOf5wRzR3DKaFQz4l1UBq+vgfsZbPG4xZb2zYkuVICQvkkdjCP27gSRYwsIX0gw== + +"@patternfly/react-styles@^5.0.0-prerelease.7": version "5.0.0-prerelease.7" - resolved "https://registry.yarnpkg.com/@patternfly/react-icons/-/react-icons-5.0.0-prerelease.7.tgz#f98dd22e363324a6174e70fcaaaa8f834316f2fc" - integrity sha512-nR4kv5pKN9csN6uZ/0HZg55ZM9S2ngpCL8s/pAc1PtwdOpvm5fUEb3HnCKJmf2pjRxPr7FKIF3aAAAGRd1ORIA== - -"@patternfly/react-styles@^5.0.0-prerelease.5": - version "5.0.0-prerelease.5" - resolved "https://registry.yarnpkg.com/@patternfly/react-styles/-/react-styles-5.0.0-prerelease.5.tgz#cdd20855331fd1fde670c764cb3ec7faf3be93e4" - integrity sha512-1hMBVpW/LXuDOyfGhI7hhaBnUJn18wh2+Zbfj3Xh4J3jhI1iVr9XIudu/rjwheCKLcELid41IYWF43Pg6FmNSQ== - -"@patternfly/react-table@^5.0.0-prerelease.13": - version "5.0.0-prerelease.13" - resolved "https://registry.yarnpkg.com/@patternfly/react-table/-/react-table-5.0.0-prerelease.13.tgz#01b99204b397f2f1e0da8a02290c050d228cf37a" - integrity sha512-523SidmitAkXHugkE8NAfcv9+uRUASAYhvNxbZ2wnB8EuO1ICD6GmPHVrbtZJl/43A7cvBJuWQ/EIVTa8bkRxQ== - dependencies: - "@patternfly/react-core" "^5.0.0-prerelease.13" - "@patternfly/react-icons" "^5.0.0-prerelease.7" - "@patternfly/react-styles" "^5.0.0-prerelease.5" - "@patternfly/react-tokens" "^5.0.0-prerelease.5" + resolved "https://registry.yarnpkg.com/@patternfly/react-styles/-/react-styles-5.0.0-prerelease.7.tgz#c7d4337c6ae5482b69ad9eb9d93bcc9509644874" + integrity sha512-TKajHVnE7z9DH+pkSNQwz0olktaAjnOtWQP4V4mzx9RmRBIcU1x+hAIQzi2zdDV1MooWry8Gsk6dRC7UI6gJVQ== + +"@patternfly/react-table@^5.0.0-prerelease.26": + version "5.0.0-prerelease.26" + resolved "https://registry.yarnpkg.com/@patternfly/react-table/-/react-table-5.0.0-prerelease.26.tgz#e4dcf3ba26b7e127df922d1609bf857de6fdb6ee" + integrity sha512-Qv0DfAobNJsgCS63+BtX9BU3tRd51DQ4UmzsG9GIpsSCXbxnQXl7hafDwnknq63K87VyzPy5D1pO0LqtaYl6rg== + dependencies: + "@patternfly/react-core" "^5.0.0-prerelease.26" + "@patternfly/react-icons" "^5.0.0-prerelease.9" + "@patternfly/react-styles" "^5.0.0-prerelease.7" + "@patternfly/react-tokens" "^5.0.0-prerelease.9" lodash "^4.17.19" tslib "^2.5.0" -"@patternfly/react-tokens@^5.0.0-prerelease.5": - version "5.0.0-prerelease.5" - resolved "https://registry.yarnpkg.com/@patternfly/react-tokens/-/react-tokens-5.0.0-prerelease.5.tgz#5b44d55439f020878dde68d13941f2560beabe25" - integrity sha512-36iQ7CuYh3OKf+TEZNSfU5Mpgi+aLJoFFA2V4YDaOL8+7RC8sFqh/dW3S9ThkjQrtc0fF7OK7mrPJzK+nQB9UQ== +"@patternfly/react-tokens@^5.0.0-prerelease.9": + version "5.0.0-prerelease.9" + resolved "https://registry.yarnpkg.com/@patternfly/react-tokens/-/react-tokens-5.0.0-prerelease.9.tgz#c972df627db20f6d5ed20754b16723d6a1b76d3e" + integrity sha512-x3kJolPS95LJSiS2n3T9KL6MNjtuM9qKKzbqK1nkiftAytubcoQ9O7ikEjDYiILHpupo5lG5H9Cr50kAwu1rsA== "@pkgjs/parseargs@^0.11.0": version "0.11.0" @@ -9384,13 +9384,6 @@ react-monaco-editor@^0.51.0: dependencies: prop-types "^15.8.1" -react-monaco-editor@^0.52.0: - version "0.52.0" - resolved "https://registry.yarnpkg.com/react-monaco-editor/-/react-monaco-editor-0.52.0.tgz#69a7c450a22830064d2fc1b446674b1b7da0f540" - integrity sha512-jhQSekf2JABbcpN45gKZlWfTS0QcBOZAbAWKGyfqy/KEcMXTwJpCOYGcn2Ur11SUUxWJUzhKjE2fx9BGBc5S8g== - dependencies: - prop-types "^15.8.1" - react-ssr-prepass@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/react-ssr-prepass/-/react-ssr-prepass-1.5.0.tgz#bc4ca7fcb52365e6aea11cc254a3d1bdcbd030c5"