@react-spectrum/tree 3.0.0-nightly.5038 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{TreeView.fdfdaa1c.css → TreeView.a32d8337.css} +112 -84
- package/dist/TreeView.a32d8337.css.map +1 -0
- package/dist/TreeView.main.js +116 -126
- package/dist/TreeView.main.js.map +1 -1
- package/dist/TreeView.mjs +117 -128
- package/dist/TreeView.module.js +117 -128
- package/dist/TreeView.module.js.map +1 -1
- package/dist/import.mjs +4 -2
- package/dist/main.js +4 -0
- package/dist/main.js.map +1 -1
- package/dist/module.js +4 -2
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts +11 -9
- package/dist/types.d.ts.map +1 -1
- package/package.json +16 -16
- package/src/TreeView.tsx +67 -84
- package/src/index.ts +3 -2
- package/dist/TreeView.fdfdaa1c.css.map +0 -1
package/src/TreeView.tsx
CHANGED
|
@@ -10,21 +10,31 @@
|
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
13
|
+
import {AriaTreeProps} from '@react-aria/tree';
|
|
14
|
+
import {
|
|
15
|
+
ButtonContext,
|
|
16
|
+
Tree,
|
|
17
|
+
TreeItem,
|
|
18
|
+
TreeItemContent,
|
|
19
|
+
TreeItemContentProps,
|
|
20
|
+
TreeItemContentRenderProps,
|
|
21
|
+
TreeItemProps,
|
|
22
|
+
TreeItemRenderProps,
|
|
23
|
+
TreeRenderProps,
|
|
24
|
+
useContextProps
|
|
25
|
+
} from 'react-aria-components';
|
|
15
26
|
import {Checkbox} from '@react-spectrum/checkbox';
|
|
16
27
|
import ChevronLeftMedium from '@spectrum-icons/ui/ChevronLeftMedium';
|
|
17
28
|
import ChevronRightMedium from '@spectrum-icons/ui/ChevronRightMedium';
|
|
18
29
|
import {DOMRef, Expandable, Key, SelectionBehavior, SpectrumSelectionProps, StyleProps} from '@react-types/shared';
|
|
30
|
+
import {focusRing, style} from '@react-spectrum/style-macro-s1' with {type: 'macro'};
|
|
19
31
|
import {isAndroid} from '@react-aria/utils';
|
|
20
|
-
import React, {createContext,
|
|
32
|
+
import React, {createContext, JSX, JSXElementConstructor, ReactElement, ReactNode, useRef} from 'react';
|
|
21
33
|
import {SlotProvider, useDOMRef, useStyleProps} from '@react-spectrum/utils';
|
|
22
|
-
import {style} from '@react-spectrum/style-macro-s1' with {type: 'macro'};
|
|
23
|
-
import {Text} from '@react-spectrum/text';
|
|
24
34
|
import {useButton} from '@react-aria/button';
|
|
25
35
|
import {useLocale} from '@react-aria/i18n';
|
|
26
36
|
|
|
27
|
-
export interface SpectrumTreeViewProps<T> extends Omit<
|
|
37
|
+
export interface SpectrumTreeViewProps<T> extends Omit<AriaTreeProps<T>, 'children'>, StyleProps, SpectrumSelectionProps, Expandable {
|
|
28
38
|
/** Provides content to display when there are no items in the tree. */
|
|
29
39
|
renderEmptyState?: () => JSX.Element,
|
|
30
40
|
/**
|
|
@@ -38,13 +48,9 @@ export interface SpectrumTreeViewProps<T> extends Omit<AriaTreeGridListProps<T>,
|
|
|
38
48
|
children?: ReactNode | ((item: T) => ReactNode)
|
|
39
49
|
}
|
|
40
50
|
|
|
41
|
-
export interface SpectrumTreeViewItemProps
|
|
51
|
+
export interface SpectrumTreeViewItemProps extends Omit<TreeItemProps, 'className' | 'style' | 'value' | 'onHoverStart' | 'onHoverEnd' | 'onHoverChange'> {
|
|
42
52
|
/** Rendered contents of the tree item or child items. */
|
|
43
|
-
children: ReactNode
|
|
44
|
-
/** Whether this item has children, even if not loaded yet. */
|
|
45
|
-
hasChildItems?: boolean,
|
|
46
|
-
/** A list of child tree item objects used when dynamically rendering the tree item children. */
|
|
47
|
-
childItems?: Iterable<T>
|
|
53
|
+
children: ReactNode
|
|
48
54
|
}
|
|
49
55
|
|
|
50
56
|
interface TreeRendererContextValue {
|
|
@@ -52,16 +58,16 @@ interface TreeRendererContextValue {
|
|
|
52
58
|
}
|
|
53
59
|
const TreeRendererContext = createContext<TreeRendererContextValue>({});
|
|
54
60
|
|
|
55
|
-
function useTreeRendererContext(): TreeRendererContextValue {
|
|
56
|
-
return useContext(TreeRendererContext)!;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
61
|
// TODO: add animations for rows appearing and disappearing
|
|
60
62
|
|
|
61
63
|
// TODO: the below is needed so the borders of the top and bottom row isn't cut off if the TreeView is wrapped within a container by always reserving the 2px needed for the
|
|
62
64
|
// keyboard focus ring. Perhaps find a different way of rendering the outlines since the top of the item doesn't
|
|
63
65
|
// scroll into view due to how the ring is offset. Alternatively, have the tree render the top/bottom outline like it does in Listview
|
|
64
66
|
const tree = style<Pick<TreeRenderProps, 'isEmpty'>>({
|
|
67
|
+
...focusRing(),
|
|
68
|
+
outlineOffset: '[-2px]', // make certain we are visible inside overflow hidden containers
|
|
69
|
+
height: 'full',
|
|
70
|
+
width: 'full',
|
|
65
71
|
borderWidth: 2,
|
|
66
72
|
boxSizing: 'border-box',
|
|
67
73
|
borderXWidth: 0,
|
|
@@ -76,19 +82,17 @@ const tree = style<Pick<TreeRenderProps, 'isEmpty'>>({
|
|
|
76
82
|
alignItems: {
|
|
77
83
|
isEmpty: 'center'
|
|
78
84
|
},
|
|
79
|
-
width: {
|
|
80
|
-
isEmpty: 'full'
|
|
81
|
-
},
|
|
82
|
-
height: {
|
|
83
|
-
isEmpty: 'full'
|
|
84
|
-
},
|
|
85
85
|
display: {
|
|
86
86
|
isEmpty: 'flex'
|
|
87
|
-
}
|
|
87
|
+
},
|
|
88
|
+
overflow: 'auto'
|
|
88
89
|
});
|
|
89
90
|
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
/**
|
|
92
|
+
* A tree view provides users with a way to navigate nested hierarchical information.
|
|
93
|
+
*/
|
|
94
|
+
export const TreeView = React.forwardRef(function TreeView<T extends object>(props: SpectrumTreeViewProps<T>, ref: DOMRef<HTMLDivElement>) {
|
|
95
|
+
let {children, selectionStyle, UNSAFE_className} = props;
|
|
92
96
|
|
|
93
97
|
let renderer;
|
|
94
98
|
if (typeof children === 'function') {
|
|
@@ -101,12 +105,12 @@ function TreeView<T extends object>(props: SpectrumTreeViewProps<T>, ref: DOMRef
|
|
|
101
105
|
|
|
102
106
|
return (
|
|
103
107
|
<TreeRendererContext.Provider value={{renderer}}>
|
|
104
|
-
<
|
|
108
|
+
<Tree {...props} {...styleProps} className={renderProps => (UNSAFE_className ?? '') + tree(renderProps)} selectionBehavior={selectionBehavior as SelectionBehavior} ref={domRef}>
|
|
105
109
|
{props.children}
|
|
106
|
-
</
|
|
110
|
+
</Tree>
|
|
107
111
|
</TreeRendererContext.Provider>
|
|
108
112
|
);
|
|
109
|
-
}
|
|
113
|
+
}) as <T>(props: SpectrumTreeViewProps<T> & {ref?: DOMRef<HTMLDivElement>}) => ReactElement;
|
|
110
114
|
|
|
111
115
|
interface TreeRowRenderProps extends TreeItemRenderProps {
|
|
112
116
|
isLink?: boolean
|
|
@@ -140,7 +144,7 @@ const treeCellGrid = style({
|
|
|
140
144
|
display: 'grid',
|
|
141
145
|
width: 'full',
|
|
142
146
|
alignItems: 'center',
|
|
143
|
-
gridTemplateColumns: ['minmax(0, auto)', 'minmax(0, auto)', 'minmax(0, auto)',
|
|
147
|
+
gridTemplateColumns: ['minmax(0, auto)', 'minmax(0, auto)', 'minmax(0, auto)', 10, 'minmax(0, auto)', '1fr', 'minmax(0, auto)', 'auto'],
|
|
144
148
|
gridTemplateRows: '1fr',
|
|
145
149
|
gridTemplateAreas: [
|
|
146
150
|
'drag-handle checkbox level-padding expand-button icon content actions actionmenu'
|
|
@@ -199,7 +203,8 @@ const treeRowOutline = style({
|
|
|
199
203
|
isSelected: {
|
|
200
204
|
default: '[-1px]',
|
|
201
205
|
isFocusVisible: '[-2px]'
|
|
202
|
-
}
|
|
206
|
+
},
|
|
207
|
+
isFirst: 0
|
|
203
208
|
},
|
|
204
209
|
bottom: 0,
|
|
205
210
|
pointerEvents: 'none',
|
|
@@ -221,52 +226,37 @@ const treeRowOutline = style({
|
|
|
221
226
|
}
|
|
222
227
|
});
|
|
223
228
|
|
|
224
|
-
export const TreeViewItem =
|
|
229
|
+
export const TreeViewItem = (props: SpectrumTreeViewItemProps) => {
|
|
225
230
|
let {
|
|
226
|
-
children,
|
|
227
|
-
childItems,
|
|
228
|
-
hasChildItems,
|
|
229
231
|
href
|
|
230
232
|
} = props;
|
|
231
233
|
|
|
232
|
-
let content;
|
|
233
|
-
let nestedRows;
|
|
234
|
-
let {renderer} = useTreeRendererContext();
|
|
235
|
-
// TODO alternative api is that we have a separate prop for the TreeItems contents and expect the child to then be
|
|
236
|
-
// a nested tree item
|
|
237
|
-
|
|
238
|
-
if (typeof children === 'string') {
|
|
239
|
-
content = <Text>{children}</Text>;
|
|
240
|
-
} else {
|
|
241
|
-
content = [];
|
|
242
|
-
nestedRows = [];
|
|
243
|
-
React.Children.forEach(children, node => {
|
|
244
|
-
if (isValidElement(node) && node.type === TreeViewItem) {
|
|
245
|
-
nestedRows.push(node);
|
|
246
|
-
} else {
|
|
247
|
-
content.push(node);
|
|
248
|
-
}
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
if (childItems != null && renderer) {
|
|
253
|
-
nestedRows = (
|
|
254
|
-
<Collection items={childItems}>
|
|
255
|
-
{renderer}
|
|
256
|
-
</Collection>
|
|
257
|
-
);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
234
|
return (
|
|
261
|
-
|
|
262
|
-
<UNSTABLE_TreeItem
|
|
235
|
+
<TreeItem
|
|
263
236
|
{...props}
|
|
264
237
|
className={renderProps => treeRow({
|
|
265
238
|
...renderProps,
|
|
266
239
|
isLink: !!href
|
|
267
|
-
})}
|
|
268
|
-
|
|
269
|
-
|
|
240
|
+
})} />
|
|
241
|
+
);
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
export interface SpectrumTreeViewItemContentProps extends Omit<TreeItemContentProps, 'children'> {
|
|
245
|
+
/** Rendered contents of the tree item or child items. */
|
|
246
|
+
children: ReactNode
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
export const TreeViewItemContent = (props: SpectrumTreeViewItemContentProps) => {
|
|
251
|
+
let {
|
|
252
|
+
children
|
|
253
|
+
} = props;
|
|
254
|
+
|
|
255
|
+
return (
|
|
256
|
+
<TreeItemContent>
|
|
257
|
+
{({isExpanded, hasChildItems, level, selectionMode, selectionBehavior, isDisabled, isSelected, isFocusVisible, state, id}) => {
|
|
258
|
+
let isFirst = state.collection.getFirstKey() === id;
|
|
259
|
+
return (
|
|
270
260
|
<div className={treeCellGrid({isDisabled})}>
|
|
271
261
|
{selectionMode !== 'none' && selectionBehavior === 'toggle' && (
|
|
272
262
|
// TODO: add transition?
|
|
@@ -275,15 +265,15 @@ export const TreeViewItem = <T extends object>(props: SpectrumTreeViewItemProps<
|
|
|
275
265
|
UNSAFE_className={treeCheckbox()}
|
|
276
266
|
UNSAFE_style={{paddingInlineEnd: '0px'}}
|
|
277
267
|
slot="selection" />
|
|
278
|
-
|
|
268
|
+
)}
|
|
279
269
|
<div style={{gridArea: 'level-padding', marginInlineEnd: `calc(${level - 1} * var(--spectrum-global-dimension-size-200))`}} />
|
|
280
270
|
{/* TODO: revisit when we do async loading, at the moment hasChildItems will only cause the chevron to be rendered, no aria/data attributes indicating the row's expandability are added */}
|
|
281
|
-
{
|
|
271
|
+
{hasChildItems && <ExpandableRowChevron isDisabled={isDisabled} isExpanded={isExpanded} />}
|
|
282
272
|
<SlotProvider
|
|
283
273
|
slots={{
|
|
284
274
|
text: {UNSAFE_className: treeContent({isDisabled})},
|
|
285
|
-
|
|
286
|
-
|
|
275
|
+
// Note there is also an issue here where these icon props are making into the action menu's icon. Resolved by 8ab0ffb276ff437a65b365c9a3be0323a1b24656
|
|
276
|
+
// but could crop up later for other components
|
|
287
277
|
icon: {UNSAFE_className: treeIcon(), size: 'S'},
|
|
288
278
|
actionButton: {UNSAFE_className: treeActions(), isQuiet: true},
|
|
289
279
|
actionGroup: {
|
|
@@ -296,14 +286,13 @@ export const TreeViewItem = <T extends object>(props: SpectrumTreeViewItemProps<
|
|
|
296
286
|
},
|
|
297
287
|
actionMenu: {UNSAFE_className: treeActionMenu(), UNSAFE_style: {marginInlineEnd: '.5rem'}, isQuiet: true}
|
|
298
288
|
}}>
|
|
299
|
-
{
|
|
289
|
+
{children}
|
|
300
290
|
</SlotProvider>
|
|
301
|
-
<div className={treeRowOutline({isFocusVisible, isSelected})} />
|
|
291
|
+
<div className={treeRowOutline({isFocusVisible, isSelected, isFirst})} />
|
|
302
292
|
</div>
|
|
303
|
-
)
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
</UNSTABLE_TreeItem>
|
|
293
|
+
);
|
|
294
|
+
}}
|
|
295
|
+
</TreeItemContent>
|
|
307
296
|
);
|
|
308
297
|
};
|
|
309
298
|
|
|
@@ -332,7 +321,7 @@ const expandButton = style<ExpandableRowChevronProps>({
|
|
|
332
321
|
});
|
|
333
322
|
|
|
334
323
|
function ExpandableRowChevron(props: ExpandableRowChevronProps) {
|
|
335
|
-
let expandButtonRef = useRef
|
|
324
|
+
let expandButtonRef = useRef(null);
|
|
336
325
|
let [fullProps, ref] = useContextProps({...props, slot: 'chevron'}, expandButtonRef, ButtonContext);
|
|
337
326
|
let {isExpanded, isDisabled} = fullProps;
|
|
338
327
|
let {direction} = useLocale();
|
|
@@ -354,9 +343,3 @@ function ExpandableRowChevron(props: ExpandableRowChevronProps) {
|
|
|
354
343
|
</span>
|
|
355
344
|
);
|
|
356
345
|
}
|
|
357
|
-
|
|
358
|
-
/**
|
|
359
|
-
* A tree view provides users with a way to navigate nested hierarchical information.
|
|
360
|
-
*/
|
|
361
|
-
const _TreeView = React.forwardRef(TreeView) as <T>(props: SpectrumTreeViewProps<T> & {ref?: DOMRef<HTMLDivElement>}) => ReactElement;
|
|
362
|
-
export {_TreeView as TreeView};
|
package/src/index.ts
CHANGED
|
@@ -12,5 +12,6 @@
|
|
|
12
12
|
|
|
13
13
|
/// <reference types="css-module-types" />
|
|
14
14
|
|
|
15
|
-
export {TreeViewItem, TreeView} from './TreeView';
|
|
16
|
-
export
|
|
15
|
+
export {TreeViewItem, TreeView, TreeViewItemContent} from './TreeView';
|
|
16
|
+
export {Collection} from 'react-aria-components';
|
|
17
|
+
export type {SpectrumTreeViewProps, SpectrumTreeViewItemProps, SpectrumTreeViewItemContentProps} from './TreeView';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"mappings":"ACAA;EAGE;;;;EAMA;;;;EAMA;;;;EAMA;;;;EAYA;;;;EAMA;;;;EApCA;;;;EAYA;;;;EAYA;;;;EAMA;;;;EAMA;;;;EAMA;;;;EAMA;;;;EAYA;;;;EAMA;;;;EAMA;;;;;EAYA;;;;EAMA;;;;EA1FA;;;;EAMA;;;;EAMA;;;;EAMA;;;;EAMA;;;;EAMA;;;;EAMA;;;;EApCA;;;;EAMA;;;;EAMA;;;;EAMA;;;;EAlBA;;;;EAMA;;;;EANA;;;;EAMA;;;;EAMA;;;;EAMA;;;;EAMA;;;;EAxBA;;;;EAMA;;;;EAMA;;;;EAMA;;;;EAMA;;;;EAxBA;;;;EAMA;;;;EANA;;;;EAMA;;;;EAMA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAMA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAMA;;;;EAYA;;;;EAMA;;;;EAMA;;;;EAMA;;;;EAMA;;;;EAYA;;;;EAMA;;;;EA9EA;;;;EAMA;;;;EAMA;;;;EAMA;;;;EAMA;;;;EAMA;;;;EAMA;;;;EAMA;;;;EAMA;;;;EAMA;;;;EAMA;;;;;;;AA/DF;;AA4CA;EACE;IACE;;;;IAAA;;;;IA8CA;;;;IAIA","sources":["f54a9241b0b1bdd2","packages/@react-spectrum/tree/src/TreeView.tsx"],"sourcesContent":["@import \"43ede2ea230cbe77\";\n@import \"d6186a3bcdea23c0\";\n@import \"9b0163e48ed44108\";\n@import \"4145f5de7372e962\";\n@import \"5c8e7aff246c25c0\";\n@import \"e6e7b4c2a4a805d7\";\n@import \"ed226d1e6a9f6d5d\";\n@import \"af6efb89500ab023\";\n@import \"5458487886ba8cfe\";\n@import \"5be3595defba4bd4\";\n","@layer a, b;\n\n@layer a {\n .wc {\n border-top-width: var(--spectrum-alias-border-size-thick, var(--spectrum-global-dimension-static-size-25));\n }\n}\n\n@layer a {\n .xc {\n border-bottom-width: var(--spectrum-alias-border-size-thick, var(--spectrum-global-dimension-static-size-25));\n }\n}\n\n@layer a {\n .ua {\n border-inline-start-width: 0px;\n }\n}\n\n@layer a {\n .va {\n border-inline-end-width: 0px;\n }\n}\n\n@layer a {\n .__ka {\n box-sizing: border-box;\n }\n}\n\n@layer a {\n .Aa {\n border-style: solid;\n }\n}\n\n@layer a {\n .ca {\n border-color: transparent;\n }\n}\n\n@layer b.a {\n @media (forced-colors: active) {\n .ca___y {\n border-color: Background;\n }\n }\n}\n\n@layer a {\n ._Vd {\n justify-content: center;\n }\n}\n\n@layer a {\n ._Uc {\n align-items: center;\n }\n}\n\n@layer a {\n .oY {\n width: 100%;\n }\n}\n\n@layer a {\n .nY {\n height: 100%;\n }\n}\n\n@layer a {\n ._Sd {\n display: flex;\n }\n}\n\n"],"names":[],"version":3,"file":"TreeView.fdfdaa1c.css.map"}
|