-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e395e5a
commit c244501
Showing
52 changed files
with
1,503 additions
and
263 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
@import url('../../styles/variable.css'); | ||
|
||
.aui--tree-picker { | ||
& .aui--tree-picker-row + .aui--tree-picker-tree { | ||
border-top: 1px solid $color-border-base; | ||
} | ||
} | ||
|
||
.aui--tree-picker-section { | ||
margin-top: 16px; | ||
margin-bottom: 16px; | ||
} | ||
|
||
.aui--tree-picker-row { | ||
padding: 0 2px; | ||
min-height: 36px; | ||
display: flex; | ||
align-items: center; | ||
position: relative; | ||
gap: 12px; | ||
border-top: 1px solid $color-border-base; | ||
|
||
& .aui--button.aui-icon { | ||
width: 24px; | ||
height: 24px; | ||
min-height: 24px; | ||
} | ||
} | ||
|
||
.aui--tree-picker-row-content { | ||
flex: 1; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import cc from 'classnames'; | ||
import { TreePickerProvider } from './TreePickerContext'; | ||
import TreePickerTree from './TreePickerTree'; | ||
import TreePickerHeader from './TreePickerHeader'; | ||
import TreePickerNode from './TreePickerNode'; | ||
import TreePickerNav from './TreePickerNav'; | ||
import TreePickerSearch from './TreePickerSearch'; | ||
|
||
import './TreePicker.css'; | ||
|
||
const TreePicker = ({ children, renderNode, className }) => { | ||
const renderNodeWithKey = React.useCallback( | ||
(node, index) => <React.Fragment key={node.id}>{renderNode(node, index)}</React.Fragment>, | ||
[renderNode] | ||
); | ||
|
||
return ( | ||
<TreePickerProvider renderNode={renderNodeWithKey}> | ||
<div className={cc('tree-picker', className)}>{children}</div> | ||
</TreePickerProvider> | ||
); | ||
}; | ||
|
||
TreePicker.propTypes = { | ||
children: PropTypes.node.isRequired, | ||
renderNode: PropTypes.func.isRequired, | ||
className: PropTypes.string, | ||
}; | ||
|
||
TreePicker.Tree = TreePickerTree; | ||
TreePicker.Header = TreePickerHeader; | ||
TreePicker.Node = TreePickerNode; | ||
TreePicker.Nav = TreePickerNav; | ||
TreePicker.Search = TreePickerSearch; | ||
|
||
export default TreePicker; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { Meta } from '@storybook/blocks'; | ||
|
||
<Meta title="Components/TreePicker" /> | ||
|
||
ok |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,114 +1,88 @@ | ||
import React from 'react'; | ||
import axios from 'axios'; | ||
import type { Meta, StoryObj } from '@storybook/react'; | ||
import _ from 'lodash'; | ||
|
||
import TreePicker from './index'; | ||
import SvgSymbol from '../SvgSymbol'; | ||
import Search from '../Search'; | ||
|
||
const meta = { | ||
title: 'Pending Review/TreePicker', | ||
title: 'Components/TreePicker', | ||
component: TreePicker, | ||
tags: ['autodocs'], | ||
} satisfies Meta<typeof TreePicker>; | ||
|
||
export default meta; | ||
|
||
type Story = StoryObj<typeof meta>; | ||
|
||
const DefaultComponent = () => { | ||
const [selectedSearchValue, setSelectedSearchValue] = React.useState(''); | ||
const [selectedNodes, setSelectedNodes] = React.useState([]); | ||
const [pickerSearchValue, setPickerSearchValue] = React.useState(''); | ||
const subTree = [ | ||
{ | ||
id: '0', | ||
label: 'Northern Territory', | ||
path: [{ id: '10', label: 'Australia' }], | ||
type: 'Territory', | ||
}, | ||
{ | ||
id: '1', | ||
label: 'Australian Capital Territory', | ||
path: [{ id: '10', label: 'Australia' }], | ||
type: 'Territory', | ||
}, | ||
{ | ||
id: '2', | ||
label: 'Victoria', | ||
path: [{ id: '10', label: 'Australia' }], | ||
type: 'State', | ||
}, | ||
]; | ||
|
||
const getSelectedNodes = () => { | ||
if (_.isEmpty(selectedSearchValue)) return selectedNodes; | ||
|
||
return _.filter(selectedNodes, ({ label }) => _.includes(label.toLowerCase(), selectedSearchValue.toLowerCase())); | ||
}; | ||
|
||
const getSubtree = () => { | ||
let treePickerPureSubtree = []; | ||
|
||
// filter out nodes that do not contain search string | ||
if (!_.isEmpty(pickerSearchValue)) { | ||
treePickerPureSubtree = _.filter(subTree, ({ label }) => | ||
_.includes(label.toLowerCase(), pickerSearchValue.toLowerCase()) | ||
); | ||
} | ||
const NodeRender = ({ node }) => ( | ||
<TreePicker.Node node={node}> | ||
<TreePicker.Node.Content>{node.label}</TreePicker.Node.Content> | ||
{node.type === 'comment' ? null : ( | ||
<TreePicker.Node.Expand | ||
className="expand" | ||
disabled={node.type === 'test'} | ||
resolveNodes={async () => { | ||
if (node.type === 'user') { | ||
const res = await axios.get(`https://dummyjson.com/users/${node.id}/posts?limit=5`); | ||
return res.data.posts.map((entry) => ({ | ||
...entry, | ||
label: entry.title, | ||
type: 'post', | ||
})); | ||
} | ||
const res = await axios.get(`https://dummyjson.com/posts/${node.id}/comments?limit=5`); | ||
|
||
// filter out nodes that do not contain the selected search string | ||
// however keep the nodes that are not selected but do not contain the selected search string | ||
if (!_.isEmpty(selectedSearchValue)) { | ||
treePickerPureSubtree = _.filter(treePickerPureSubtree, ({ id, label }) => { | ||
if (_.find(selectedNodes, { id })) { | ||
return _.includes(label.toLowerCase(), selectedSearchValue.toLowerCase()); | ||
} | ||
return res.data.comments.map((entry) => ({ | ||
...entry, | ||
label: entry.body, | ||
type: 'comment', | ||
})); | ||
}} | ||
/> | ||
)} | ||
<TreePicker.Node.Add | ||
disabled={node.type !== 'comment'} | ||
onAdd={() => { | ||
// eslint-disable-next-line no-console | ||
console.log(`Added ${node.id}: ${node.label}`); | ||
}} | ||
/> | ||
</TreePicker.Node> | ||
); | ||
|
||
return true; | ||
}); | ||
} | ||
export const Default: Story = { | ||
args: { | ||
renderNode: (node) => <NodeRender node={node} />, | ||
|
||
return treePickerPureSubtree; | ||
}; | ||
children: ( | ||
<> | ||
<TreePicker.Nav /> | ||
<TreePicker.Header>Name</TreePicker.Header> | ||
<TreePicker.Search | ||
resolveNodes={async (searchText) => { | ||
const res = await axios.get(`https://dummyjson.com/posts/search?q=${searchText}`); | ||
|
||
return ( | ||
<div style={{ width: 900 }}> | ||
<TreePicker | ||
itemType={'segment value'} | ||
hideIcon | ||
selectedNodes={getSelectedNodes()} | ||
subtree={getSubtree()} | ||
emptySvgSymbol={ | ||
<SvgSymbol classSuffixes={['gray-darker', '70']} href="/svg-symbols.svg#checklist-incomplete" isCircle /> | ||
} | ||
emptySelectedListText={ | ||
<div> | ||
<b>Choose items of interest</b> | ||
</div> | ||
} | ||
initialStateNode={ | ||
<div> | ||
<b>Start by searching for items</b> | ||
</div> | ||
} | ||
searchValue={pickerSearchValue} | ||
onChange={setPickerSearchValue} | ||
searchOnClear={() => setPickerSearchValue('')} | ||
includeNode={(node) => setSelectedNodes(_.concat([], selectedNodes, node))} | ||
removeNode={(node) => setSelectedNodes(_.reject(selectedNodes, { id: node.id }))} | ||
additionalClassNames={pickerSearchValue ? undefined : ['background-highlighted', 'test-class']} | ||
selectedTopSearch={ | ||
<div className="selected-search"> | ||
<Search onSearch={setSelectedSearchValue} /> | ||
</div> | ||
} | ||
/> | ||
return res.data.posts.map((post) => ({ | ||
...post, | ||
label: post.title, | ||
type: 'post', | ||
})); | ||
}} | ||
/> | ||
<TreePicker.Tree | ||
resolveRootNodes={async () => { | ||
const res = await axios.get('https://dummyjson.com/users?limit=5'); | ||
return res.data.users.map((entry) => ({ | ||
...entry, | ||
label: entry.firstName + ' ' + entry.lastName, | ||
type: 'user', | ||
})); | ||
}} | ||
/> | ||
</> | ||
), | ||
}, | ||
render: (args) => ( | ||
<div style={{ width: 500 }}> | ||
<TreePicker {...args} /> | ||
</div> | ||
); | ||
}; | ||
|
||
export const Default: Story = { | ||
args: {}, | ||
render: () => DefaultComponent(), | ||
), | ||
}; |
Oops, something went wrong.