Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
1f9d3ef
add react-virtualized to package and yarn lock
silviuaavram Sep 4, 2019
ed9b21b
add virtualized render prop to Tree
silviuaavram Sep 4, 2019
36b2383
add virtualized tree in prototypes
silviuaavram Sep 4, 2019
0e39d1f
add alternative solution in comments
silviuaavram Sep 4, 2019
5f016f5
add back as any from merging master
silviuaavram Sep 5, 2019
d4fe288
have refs for all items
silviuaavram Sep 5, 2019
a84c9d1
merge master
silviuaavram Sep 9, 2019
5b9404e
fix the cloneElement approach
silviuaavram Sep 9, 2019
b3bd3f9
fix ref issue
silviuaavram Sep 9, 2019
48e33cd
increase virtualized tree size
silviuaavram Sep 9, 2019
47d0546
rename the render prop
silviuaavram Sep 9, 2019
e170048
Merge branch 'master' into feat/add-virtualized-tree-prototype
silviuaavram Sep 10, 2019
4db50b7
add changelog
silviuaavram Sep 10, 2019
84720aa
fix use of prop name
silviuaavram Sep 10, 2019
14737cc
move items code from prototype
silviuaavram Sep 10, 2019
9b77112
address code review
silviuaavram Sep 10, 2019
52bfc8c
make prototype public
silviuaavram Sep 11, 2019
188ae22
Merge branch 'master' into feat/add-virtualized-tree-prototype
silviuaavram Sep 11, 2019
d05647c
use lodash times function
silviuaavram Sep 12, 2019
a75d594
Merge branch 'feat/add-virtualized-tree-prototype' of https://github.…
silviuaavram Sep 12, 2019
29fd807
Merge branch 'master' into feat/add-virtualized-tree-prototype
silviuaavram Sep 12, 2019
aeabfd8
Merge branch 'master' into feat/add-virtualized-tree-prototype
silviuaavram Sep 13, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

### Documentation
- Fix broken code editor in some doc site examples and improve error experience @levithomason ([#1906](https://github.com/stardust-ui/react/pull/1906))
- Add `VirtualizedTree` prototype @silviuavram ([#1890](https://github.com/stardust-ui/react/pull/1890))

<!--------------------------------[ v0.38.0 ]------------------------------- -->
## [v0.38.0](https://github.com/stardust-ui/react/tree/v0.38.0) (2019-09-06)
Expand Down
5 changes: 5 additions & 0 deletions docs/src/components/Sidebar/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,11 @@ class Sidebar extends React.Component<any, any> {
title: { content: 'MenuButton', as: NavLink, to: '/menu-button' },
public: false,
},
{
key: 'virtualized-tree',
title: { content: 'VirtualizedTree', as: NavLink, to: '/virtualized-tree' },
public: true,
},
{
key: 'copy-to-clipboard',
title: { content: 'Copy to Clipboard', as: NavLink, to: '/prototype-copy-to-clipboard' },
Expand Down
48 changes: 48 additions & 0 deletions docs/src/prototypes/VirtualizedTree/VirtualizedTree.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import * as React from 'react'
import { Tree } from '@stardust-ui/react'
import { CellMeasurer, CellMeasurerCache, List as ReactVirtualizedList } from 'react-virtualized'
import getItems from './itemsGenerator'

interface TreeVirtualizerProps {
renderedItems: React.ReactElement[]
}

function TreeVirtualizer(props: TreeVirtualizerProps) {
const cache = new CellMeasurerCache({
defaultHeight: 20,
fixedWidth: true,
})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it be persistent between renders?

const [cache] = React.useState(() => 
  new CellMeasurerCache({
    defaultHeight: 20,
    fixedWidth: true,
  })
)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


const rowRenderer = ({ index, isScrolling, key, parent, style }) => {
const { renderedItems } = props

return (
<CellMeasurer cache={cache} columnIndex={0} key={key} parent={parent} rowIndex={index}>
{React.cloneElement(renderedItems[index], { style })}
</CellMeasurer>
)
}

return (
<ReactVirtualizedList
deferredMeasurementCache={cache}
rowHeight={cache.rowHeight}
rowRenderer={rowRenderer}
estimatedRowSize={20}
height={300}
rowCount={props.renderedItems.length}
width={600}
/>
)
}

const items = getItems()

const VirtualizedTreePrototype = () => (
<Tree
items={items}
renderedItems={renderedItems => <TreeVirtualizer renderedItems={renderedItems} />}
/>
)

export default VirtualizedTreePrototype
11 changes: 11 additions & 0 deletions docs/src/prototypes/VirtualizedTree/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as React from 'react'
import VirtualizedTree from './VirtualizedTree'
import { PrototypeSection, ComponentPrototype } from '../Prototypes'

export default () => (
<PrototypeSection title="VirtualizedTree">
<ComponentPrototype title="Virtualized Tree" description="Tree with its content virtualized.">
<VirtualizedTree />
</ComponentPrototype>
</PrototypeSection>
)
24 changes: 24 additions & 0 deletions docs/src/prototypes/VirtualizedTree/itemsGenerator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import * as _ from 'lodash'

function getItems(minItems = 20, maxItems = 40, maxLevel = 1) {
function getItemsNumber(minItems, maxItems) {
return _.random(minItems, maxItems)
}

function generateLevel(level, parent = '') {
const result = []
_.times(getItemsNumber(minItems, maxItems), index => {
const item = {
id: `${parent}${parent ? '-' : ''}${index}`,
title: `Tree-Item-${parent}${parent ? '-' : ''}${index}`,
...(level < maxLevel && { items: generateLevel(level + 1, `${parent}${index}`) }),
}
result.push(item)
})
return result
}

return generateLevel(0)
}

export default getItems
2 changes: 2 additions & 0 deletions docs/src/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import IconViewerPrototype from './prototypes/IconViewer'
import MenuButtonPrototype from './prototypes/MenuButton'
import AlertsPrototype from './prototypes/alerts'
import NestedPopupsAndDialogsPrototype from './prototypes/NestedPopupsAndDialogs'
import VirtualizedTreePrototype from './prototypes/VirtualizedTree'
import CopyToClipboardPrototype from './prototypes/CopyToClipboard'
import ParticipantsListPrototype from './prototypes/ParticipantsList'

Expand Down Expand Up @@ -77,6 +78,7 @@ const Routes = () => (
path="/prototype-nested-popups-and-dialogs"
component={NestedPopupsAndDialogsPrototype}
/>
<Route exact path="/virtualized-tree" component={VirtualizedTreePrototype} />
<Route exact path="/prototype-copy-to-clipboard" component={CopyToClipboardPrototype} />
<Route exact path="/faq" component={FAQ} />
<Route exact path="/accessibility" component={Accessibility} />
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@
"react-router-dom": "^5.0.1",
"react-source-render": "3.0.0-5",
"react-test-renderer": "^16.8.5",
"react-virtualized": "^9.21.1",
"react-vis": "^1.11.6",
"react-visibility-sensor": "^5.1.0",
"read-package-json": "^2.0.13",
Expand Down
34 changes: 19 additions & 15 deletions packages/react/src/components/Tree/Tree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@ export interface TreeProps extends UIComponentProps, ChildrenComponentProps {
* @param {ReactNode|ReactNodeArray} children - The computed children for this slot.
*/
renderItemTitle?: ShorthandRenderFunction<TreeTitleProps>

/**
* Callback that provides rendered tree items to be used by react-virtualized for instance.
* Acts as a render prop, with the rendered tree items being the re-used logic.
*
* @param {React.ReactElement[]} renderedItem The array of rendered items.
* @return {React.ReactNode} The render prop result.
*/
renderedItems?: (renderedItems: React.ReactElement[]) => React.ReactNode
}

export interface TreeItemForRenderProps {
Expand Down Expand Up @@ -93,6 +102,7 @@ class Tree extends AutoControlledComponent<WithAsProp<TreeProps>, TreeState> {
exclusive: PropTypes.bool,
items: customPropTypes.collectionShorthand,
renderItemTitle: PropTypes.func,
renderedItems: PropTypes.func,
}

static defaultProps = {
Expand Down Expand Up @@ -264,32 +274,22 @@ class Tree extends AutoControlledComponent<WithAsProp<TreeProps>, TreeState> {
const { elementRef, ...restItemForRender } = itemForRender
const isSubtree = hasSubtree(item)
const isSubtreeOpen = isSubtree && this.isActiveItem(item['id'])

const renderedItem = TreeItem.create(item, {
defaultProps: {
className: Tree.slotClassNames.item,
open: isSubtreeOpen,
renderItemTitle,
key: item['id'],
contentRef: elementRef,
...restItemForRender,
},
overrideProps: this.handleTreeItemOverrides,
})

// Only need refs of the items that spawn subtrees, when they need to be focused
// by any of their children, using Arrow Left.
const finalRenderedItem = isSubtree ? (
<Ref key={item['id']} innerRef={elementRef}>
{renderedItem}
</Ref>
) : (
renderedItem
)

return [
...renderedItems,
finalRenderedItem,
...([isSubtreeOpen ? renderItems(item['items']) : []] as any),
renderedItem,
...(isSubtreeOpen ? renderItems(item['items']) : ([] as any)),
]
},
[],
Expand All @@ -300,7 +300,7 @@ class Tree extends AutoControlledComponent<WithAsProp<TreeProps>, TreeState> {
}

renderComponent({ ElementType, classes, accessibility, unhandledProps, styles, variables }) {
const { children } = this.props
const { children, renderedItems } = this.props

return (
<Ref innerRef={this.treeRef}>
Expand All @@ -311,7 +311,11 @@ class Tree extends AutoControlledComponent<WithAsProp<TreeProps>, TreeState> {
{...unhandledProps}
{...applyAccessibilityKeyHandlers(accessibility.keyHandlers.root, unhandledProps)}
>
{childrenExist(children) ? children : this.renderContent()}
{childrenExist(children)
? children
: renderedItems
? renderedItems(this.renderContent())
: this.renderContent()}
</ElementType>
</Ref>
)
Expand Down
12 changes: 9 additions & 3 deletions packages/react/src/components/Tree/TreeItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as _ from 'lodash'
import * as PropTypes from 'prop-types'
import * as React from 'react'

import { Ref } from '@stardust-ui/react-component-ref'
import TreeTitle, { TreeTitleProps } from './TreeTitle'
import { treeItemBehavior } from '../../lib/accessibility'
import { Accessibility } from '../../lib/accessibility/types'
Expand Down Expand Up @@ -45,6 +46,9 @@ export interface TreeItemProps extends UIComponentProps, ChildrenComponentProps
/** Array of props for sub tree. */
items?: ShorthandCollection<TreeItemProps>

/** Ref for the item DOM element. */
contentRef?: React.Ref<HTMLElement>

/** Level of the tree/subtree that contains this item. */
level?: number

Expand Down Expand Up @@ -104,6 +108,7 @@ class TreeItem extends UIComponent<WithAsProp<TreeItemProps>, TreeItemState> {
...commonPropTypes.createCommon({
content: false,
}),
contentRef: customPropTypes.ref,
id: PropTypes.string.isRequired,
index: PropTypes.number,
items: customPropTypes.collectionShorthand,
Expand Down Expand Up @@ -206,9 +211,8 @@ class TreeItem extends UIComponent<WithAsProp<TreeItemProps>, TreeItemState> {
}

renderComponent({ ElementType, accessibility, classes, unhandledProps, styles, variables }) {
const { children } = this.props

return (
const { children, contentRef } = this.props
const element = (
<ElementType
className={classes.root}
{...accessibility.attributes.root}
Expand All @@ -219,6 +223,8 @@ class TreeItem extends UIComponent<WithAsProp<TreeItemProps>, TreeItemState> {
{childrenExist(children) ? children : this.renderContent()}
</ElementType>
)

return contentRef ? <Ref innerRef={contentRef}>{element}</Ref> : element
}
}

Expand Down
32 changes: 31 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3754,6 +3754,11 @@ cloneable-readable@^1.0.0:
process-nextick-args "^2.0.0"
readable-stream "^2.3.5"

clsx@^1.0.1:
version "1.0.4"
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.0.4.tgz#0c0171f6d5cb2fe83848463c15fcc26b4df8c2ec"
integrity sha512-1mQ557MIZTrL/140j+JVdRM6e31/OA4vTYxXgqIIZlndyfjHpyawKZia1Im05Vp9BWmImkcNrNtFYQMyFcgJDg==

cmd-shim@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-2.0.2.tgz#6fcbda99483a8fd15d7d30a196ca69d688a2efdb"
Expand Down Expand Up @@ -4937,6 +4942,13 @@ dom-css@^2.0.0:
prefix-style "2.0.1"
to-camel-case "1.0.0"

"dom-helpers@^2.4.0 || ^3.0.0":
version "3.4.0"
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8"
integrity sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==
dependencies:
"@babel/runtime" "^7.1.2"

dom-serializer@0, dom-serializer@~0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82"
Expand Down Expand Up @@ -9104,6 +9116,11 @@ liftoff@^3.1.0:
rechoir "^0.6.2"
resolve "^1.1.7"

linear-layout-vector@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/linear-layout-vector/-/linear-layout-vector-0.0.1.tgz#398114d7303b6ecc7fd6b273af7b8401d8ba9c70"
integrity sha1-OYEU1zA7bsx/1rJzr3uEAdi6nHA=

lint-staged@^7.0.2:
version "7.2.0"
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-7.2.0.tgz#bdf4bb7f2f37fe689acfaec9999db288a5b26888"
Expand Down Expand Up @@ -9536,7 +9553,7 @@ longest-streak@^1.0.0:
resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-1.0.0.tgz#d06597c4d4c31b52ccb1f5d8f8fe7148eafd6965"
integrity sha1-0GWXxNTDG1LMsfXY+P5xSOr9aWU=

loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
Expand Down Expand Up @@ -12047,6 +12064,19 @@ react-test-renderer@^16.0.0-0, react-test-renderer@^16.8.5:
react-is "^16.8.6"
scheduler "^0.13.6"

react-virtualized@^9.21.1:
version "9.21.1"
resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.21.1.tgz#4dbbf8f0a1420e2de3abf28fbb77120815277b3a"
integrity sha512-E53vFjRRMCyUTEKuDLuGH1ld/9TFzjf/fFW816PE4HFXWZorESbSTYtiZz1oAjra0MminaUU1EnvUxoGuEFFPA==
dependencies:
babel-runtime "^6.26.0"
clsx "^1.0.1"
dom-helpers "^2.4.0 || ^3.0.0"
linear-layout-vector "0.0.1"
loose-envify "^1.3.0"
prop-types "^15.6.0"
react-lifecycles-compat "^3.0.4"

react-vis@^1.11.6:
version "1.11.6"
resolved "https://registry.yarnpkg.com/react-vis/-/react-vis-1.11.6.tgz#4616968ac6dfbd95491d778e70ad26956fd2fdab"
Expand Down