@react-spectrum/s2 3.0.0-nightly-fd7075c5f-250128 → 3.0.0-nightly-e3ed3c7f6-250130
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/Accordion.cjs +3 -3
- package/dist/Accordion.css +2 -2
- package/dist/Accordion.mjs +3 -3
- package/dist/ActionBar.cjs +47 -47
- package/dist/ActionBar.css +51 -51
- package/dist/ActionBar.mjs +47 -47
- package/dist/ActionButton.cjs +97 -97
- package/dist/ActionButton.css +96 -96
- package/dist/ActionButton.mjs +97 -97
- package/dist/ActionButtonGroup.cjs +11 -11
- package/dist/ActionButtonGroup.css +9 -9
- package/dist/ActionButtonGroup.mjs +11 -11
- package/dist/AlertDialog.cjs +3 -3
- package/dist/AlertDialog.css +3 -3
- package/dist/AlertDialog.mjs +3 -3
- package/dist/Avatar.cjs +17 -17
- package/dist/Avatar.css +14 -14
- package/dist/Avatar.mjs +17 -17
- package/dist/AvatarGroup.cjs +100 -100
- package/dist/AvatarGroup.css +34 -34
- package/dist/AvatarGroup.mjs +100 -100
- package/dist/Badge.cjs +91 -67
- package/dist/Badge.cjs.map +1 -1
- package/dist/Badge.css +163 -91
- package/dist/Badge.css.map +1 -1
- package/dist/Badge.mjs +91 -67
- package/dist/Badge.mjs.map +1 -1
- package/dist/Breadcrumbs.cjs +115 -115
- package/dist/Breadcrumbs.css +89 -89
- package/dist/Breadcrumbs.mjs +115 -115
- package/dist/Button.cjs +236 -152
- package/dist/Button.cjs.map +1 -1
- package/dist/Button.css +309 -165
- package/dist/Button.css.map +1 -1
- package/dist/Button.mjs +236 -152
- package/dist/Button.mjs.map +1 -1
- package/dist/ButtonGroup.cjs +19 -19
- package/dist/ButtonGroup.css +15 -15
- package/dist/ButtonGroup.mjs +19 -19
- package/dist/Card.cjs +264 -261
- package/dist/Card.cjs.map +1 -1
- package/dist/Card.css +210 -198
- package/dist/Card.css.map +1 -1
- package/dist/Card.mjs +264 -261
- package/dist/Card.mjs.map +1 -1
- package/dist/CardView.cjs +15 -15
- package/dist/CardView.css +18 -18
- package/dist/CardView.mjs +15 -15
- package/dist/CenterBaseline.cjs +1 -1
- package/dist/CenterBaseline.css +2 -2
- package/dist/CenterBaseline.mjs +1 -1
- package/dist/Checkbox.cjs +124 -73
- package/dist/Checkbox.cjs.map +1 -1
- package/dist/Checkbox.css +201 -81
- package/dist/Checkbox.css.map +1 -1
- package/dist/Checkbox.mjs +124 -73
- package/dist/Checkbox.mjs.map +1 -1
- package/dist/CheckboxGroup.cjs +49 -49
- package/dist/CheckboxGroup.css +41 -41
- package/dist/CheckboxGroup.mjs +49 -49
- package/dist/ClearButton.cjs +15 -15
- package/dist/ClearButton.css +17 -17
- package/dist/ClearButton.mjs +15 -15
- package/dist/CloseButton.cjs +35 -35
- package/dist/CloseButton.css +33 -33
- package/dist/CloseButton.mjs +35 -35
- package/dist/ColorArea.cjs +22 -22
- package/dist/ColorArea.css +15 -15
- package/dist/ColorArea.mjs +22 -22
- package/dist/ColorField.cjs +38 -38
- package/dist/ColorField.css +32 -32
- package/dist/ColorField.mjs +38 -38
- package/dist/ColorHandle.cjs +27 -21
- package/dist/ColorHandle.cjs.map +1 -1
- package/dist/ColorHandle.css +93 -45
- package/dist/ColorHandle.css.map +1 -1
- package/dist/ColorHandle.mjs +27 -21
- package/dist/ColorHandle.mjs.map +1 -1
- package/dist/ColorSlider.cjs +52 -52
- package/dist/ColorSlider.css +51 -51
- package/dist/ColorSlider.mjs +52 -52
- package/dist/ColorSwatch.cjs +27 -24
- package/dist/ColorSwatch.cjs.map +1 -1
- package/dist/ColorSwatch.css +41 -29
- package/dist/ColorSwatch.css.map +1 -1
- package/dist/ColorSwatch.mjs +27 -24
- package/dist/ColorSwatch.mjs.map +1 -1
- package/dist/ColorSwatchPicker.cjs +23 -23
- package/dist/ColorSwatchPicker.css +60 -48
- package/dist/ColorSwatchPicker.css.map +1 -1
- package/dist/ColorSwatchPicker.mjs +23 -23
- package/dist/ColorWheel.cjs +22 -22
- package/dist/ColorWheel.css +16 -16
- package/dist/ColorWheel.mjs +22 -22
- package/dist/ComboBox.cjs +80 -80
- package/dist/ComboBox.css +88 -88
- package/dist/ComboBox.mjs +80 -80
- package/dist/ContextualHelp.cjs +5 -5
- package/dist/ContextualHelp.css +38 -38
- package/dist/ContextualHelp.mjs +5 -5
- package/dist/CustomDialog.cjs +31 -31
- package/dist/CustomDialog.css +25 -25
- package/dist/CustomDialog.mjs +31 -31
- package/dist/Dialog.cjs +17 -17
- package/dist/Dialog.css +64 -64
- package/dist/Dialog.mjs +17 -17
- package/dist/Disclosure.cjs +111 -108
- package/dist/Disclosure.cjs.map +1 -1
- package/dist/Disclosure.css +124 -112
- package/dist/Disclosure.css.map +1 -1
- package/dist/Disclosure.mjs +111 -108
- package/dist/Disclosure.mjs.map +1 -1
- package/dist/Divider.cjs +26 -26
- package/dist/Divider.css +16 -16
- package/dist/Divider.mjs +26 -26
- package/dist/DropZone.cjs +56 -47
- package/dist/DropZone.cjs.map +1 -1
- package/dist/DropZone.css +80 -56
- package/dist/DropZone.css.map +1 -1
- package/dist/DropZone.mjs +56 -47
- package/dist/DropZone.mjs.map +1 -1
- package/dist/Field.cjs +204 -150
- package/dist/Field.cjs.map +1 -1
- package/dist/Field.css +246 -150
- package/dist/Field.css.map +1 -1
- package/dist/Field.mjs +204 -150
- package/dist/Field.mjs.map +1 -1
- package/dist/Form.cjs +10 -10
- package/dist/Form.css +9 -9
- package/dist/Form.mjs +10 -10
- package/dist/FullscreenDialog.cjs +5 -5
- package/dist/FullscreenDialog.css +72 -72
- package/dist/FullscreenDialog.mjs +5 -5
- package/dist/IllustratedMessage.cjs +134 -134
- package/dist/IllustratedMessage.css +69 -69
- package/dist/IllustratedMessage.mjs +134 -134
- package/dist/Image.cjs +12 -12
- package/dist/Image.css +13 -13
- package/dist/Image.mjs +12 -12
- package/dist/InlineAlert.cjs +104 -77
- package/dist/InlineAlert.cjs.map +1 -1
- package/dist/InlineAlert.css +149 -77
- package/dist/InlineAlert.css.map +1 -1
- package/dist/InlineAlert.mjs +104 -77
- package/dist/InlineAlert.mjs.map +1 -1
- package/dist/Link.cjs +31 -31
- package/dist/Link.css +30 -30
- package/dist/Link.mjs +31 -31
- package/dist/Menu.cjs +269 -264
- package/dist/Menu.cjs.map +1 -1
- package/dist/Menu.css +152 -152
- package/dist/Menu.css.map +1 -1
- package/dist/Menu.mjs +270 -265
- package/dist/Menu.mjs.map +1 -1
- package/dist/Meter.cjs +85 -85
- package/dist/Meter.css +81 -81
- package/dist/Meter.mjs +85 -85
- package/dist/Modal.cjs +48 -48
- package/dist/Modal.css +46 -46
- package/dist/Modal.mjs +48 -48
- package/dist/NumberField.cjs +115 -115
- package/dist/NumberField.css +114 -114
- package/dist/NumberField.mjs +115 -115
- package/dist/Picker.cjs +193 -175
- package/dist/Picker.cjs.map +1 -1
- package/dist/Picker.css +223 -163
- package/dist/Picker.css.map +1 -1
- package/dist/Picker.mjs +193 -175
- package/dist/Picker.mjs.map +1 -1
- package/dist/Popover.cjs +84 -78
- package/dist/Popover.cjs.map +1 -1
- package/dist/Popover.css +89 -65
- package/dist/Popover.css.map +1 -1
- package/dist/Popover.mjs +84 -78
- package/dist/Popover.mjs.map +1 -1
- package/dist/ProgressBar.cjs +98 -98
- package/dist/ProgressBar.css +92 -92
- package/dist/ProgressBar.mjs +98 -98
- package/dist/ProgressCircle.cjs +17 -17
- package/dist/ProgressCircle.css +15 -15
- package/dist/ProgressCircle.mjs +17 -17
- package/dist/Provider.cjs +4 -4
- package/dist/Provider.css +5 -5
- package/dist/Provider.mjs +4 -4
- package/dist/Radio.cjs +152 -80
- package/dist/Radio.cjs.map +1 -1
- package/dist/Radio.css +240 -96
- package/dist/Radio.css.map +1 -1
- package/dist/Radio.mjs +152 -80
- package/dist/Radio.mjs.map +1 -1
- package/dist/RadioGroup.cjs +47 -47
- package/dist/RadioGroup.css +41 -41
- package/dist/RadioGroup.mjs +47 -47
- package/dist/SearchField.cjs +42 -42
- package/dist/SearchField.css +47 -47
- package/dist/SearchField.mjs +42 -42
- package/dist/SegmentedControl.cjs +101 -89
- package/dist/SegmentedControl.cjs.map +1 -1
- package/dist/SegmentedControl.css +140 -92
- package/dist/SegmentedControl.css.map +1 -1
- package/dist/SegmentedControl.mjs +101 -89
- package/dist/SegmentedControl.mjs.map +1 -1
- package/dist/Slider.cjs +229 -196
- package/dist/Slider.cjs.map +1 -1
- package/dist/Slider.css +221 -149
- package/dist/Slider.css.map +1 -1
- package/dist/Slider.mjs +229 -196
- package/dist/Slider.mjs.map +1 -1
- package/dist/StatusLight.cjs +56 -56
- package/dist/StatusLight.css +59 -59
- package/dist/StatusLight.mjs +56 -56
- package/dist/Switch.cjs +107 -74
- package/dist/Switch.cjs.map +1 -1
- package/dist/Switch.css +141 -69
- package/dist/Switch.css.map +1 -1
- package/dist/Switch.mjs +107 -74
- package/dist/Switch.mjs.map +1 -1
- package/dist/TableView.cjs +280 -253
- package/dist/TableView.cjs.map +1 -1
- package/dist/TableView.css +199 -163
- package/dist/TableView.css.map +1 -1
- package/dist/TableView.mjs +280 -253
- package/dist/TableView.mjs.map +1 -1
- package/dist/Tabs.cjs +83 -83
- package/dist/Tabs.css +58 -58
- package/dist/Tabs.mjs +83 -83
- package/dist/TagGroup.cjs +148 -148
- package/dist/TagGroup.css +134 -134
- package/dist/TagGroup.mjs +148 -148
- package/dist/TextField.cjs +59 -59
- package/dist/TextField.css +62 -62
- package/dist/TextField.mjs +59 -59
- package/dist/ToggleButton.cjs +3 -3
- package/dist/ToggleButton.css +12 -12
- package/dist/ToggleButton.mjs +3 -3
- package/dist/Tooltip.cjs +60 -57
- package/dist/Tooltip.cjs.map +1 -1
- package/dist/Tooltip.css +83 -71
- package/dist/Tooltip.css.map +1 -1
- package/dist/Tooltip.mjs +60 -57
- package/dist/Tooltip.mjs.map +1 -1
- package/dist/TreeView.cjs +465 -0
- package/dist/TreeView.cjs.map +1 -0
- package/dist/TreeView.css +632 -0
- package/dist/TreeView.css.map +1 -0
- package/dist/TreeView.mjs +455 -0
- package/dist/TreeView.mjs.map +1 -0
- package/dist/main.cjs +4 -0
- package/dist/main.cjs.map +1 -1
- package/dist/module.mjs +3 -1
- package/dist/module.mjs.map +1 -1
- package/dist/types.d.ts +21 -1
- package/dist/types.d.ts.map +1 -1
- package/icons/Skeleton.cjs +2 -2
- package/icons/Skeleton.css +5 -5
- package/icons/Skeleton.mjs +2 -2
- package/package.json +20 -19
- package/src/Menu.tsx +2 -0
- package/src/TreeView.tsx +497 -0
- package/src/index.ts +2 -0
- package/style/__tests__/style-macro.test.js +18 -18
- package/style/dist/spectrum-theme.cjs +20 -10
- package/style/dist/spectrum-theme.cjs.map +1 -1
- package/style/dist/spectrum-theme.mjs +20 -10
- package/style/dist/spectrum-theme.mjs.map +1 -1
- package/style/dist/types.d.ts +4 -0
- package/style/dist/types.d.ts.map +1 -1
- package/style/spectrum-theme.ts +18 -11
package/src/TreeView.tsx
ADDED
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2024 Adobe. All rights reserved.
|
|
3
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
*
|
|
7
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
* governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {ActionButtonGroupContext} from './ActionButtonGroup';
|
|
14
|
+
import {ActionMenuContext} from './ActionMenu';
|
|
15
|
+
import {
|
|
16
|
+
Button,
|
|
17
|
+
ButtonContext,
|
|
18
|
+
Collection,
|
|
19
|
+
Provider,
|
|
20
|
+
TreeItemProps as RACTreeItemProps,
|
|
21
|
+
TreeProps as RACTreeProps,
|
|
22
|
+
UNSTABLE_ListLayout,
|
|
23
|
+
UNSTABLE_Tree,
|
|
24
|
+
UNSTABLE_TreeItem,
|
|
25
|
+
UNSTABLE_TreeItemContent,
|
|
26
|
+
UNSTABLE_Virtualizer,
|
|
27
|
+
useContextProps
|
|
28
|
+
} from 'react-aria-components';
|
|
29
|
+
import {centerBaseline} from './CenterBaseline';
|
|
30
|
+
import {Checkbox} from './Checkbox';
|
|
31
|
+
import Chevron from '../ui-icons/Chevron';
|
|
32
|
+
import {colorMix, fontRelative, lightDark, style} from '../style' with {type: 'macro'};
|
|
33
|
+
import {DOMRef, Key} from '@react-types/shared';
|
|
34
|
+
import {getAllowedOverrides, StylesPropWithHeight, UnsafeStyles} from './style-utils' with {type: 'macro'};
|
|
35
|
+
import {IconContext} from './Icon';
|
|
36
|
+
import {isAndroid} from '@react-aria/utils';
|
|
37
|
+
import {raw} from '../style/style-macro' with {type: 'macro'};
|
|
38
|
+
import React, {createContext, forwardRef, isValidElement, JSXElementConstructor, ReactElement, useContext, useMemo, useRef} from 'react';
|
|
39
|
+
import {Text, TextContext} from './Content';
|
|
40
|
+
import {useDOMRef} from '@react-spectrum/utils';
|
|
41
|
+
import {useLocale} from 'react-aria';
|
|
42
|
+
|
|
43
|
+
interface S2TreeProps {
|
|
44
|
+
// Only detatched is supported right now with the current styles from Spectrum
|
|
45
|
+
isDetached?: boolean,
|
|
46
|
+
onAction?: (key: Key) => void,
|
|
47
|
+
// not fully supported yet
|
|
48
|
+
isEmphasized?: boolean
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface TreeViewProps extends Omit<RACTreeProps<any>, 'style' | 'className' | 'onRowAction' | 'selectionBehavior' | 'onScroll' | 'onCellAction' | 'dragAndDropHooks'>, UnsafeStyles, S2TreeProps {
|
|
52
|
+
/** Spectrum-defined styles, returned by the `style()` macro. */
|
|
53
|
+
styles?: StylesPropWithHeight
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface TreeViewItemProps<T extends object = object> extends Omit<RACTreeItemProps, 'className' | 'style'> {
|
|
57
|
+
/** Whether this item has children, even if not loaded yet. */
|
|
58
|
+
hasChildItems?: boolean,
|
|
59
|
+
/** A list of child tree item objects used when dynamically rendering the tree item children. */
|
|
60
|
+
childItems?: Iterable<T>
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
interface TreeRendererContextValue {
|
|
64
|
+
renderer?: (item) => ReactElement<any, string | JSXElementConstructor<any>>
|
|
65
|
+
}
|
|
66
|
+
const TreeRendererContext = createContext<TreeRendererContextValue>({});
|
|
67
|
+
|
|
68
|
+
function useTreeRendererContext(): TreeRendererContextValue {
|
|
69
|
+
return useContext(TreeRendererContext)!;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
let InternalTreeContext = createContext<{isDetached?: boolean, isEmphasized?: boolean}>({});
|
|
74
|
+
|
|
75
|
+
// 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
|
|
76
|
+
// keyboard focus ring. Perhaps find a different way of rendering the outlines since the top of the item doesn't
|
|
77
|
+
// scroll into view due to how the ring is offset. Alternatively, have the tree render the top/bottom outline like it does in Listview
|
|
78
|
+
const tree = style({
|
|
79
|
+
userSelect: 'none',
|
|
80
|
+
minHeight: 0,
|
|
81
|
+
minWidth: 0,
|
|
82
|
+
width: 'full',
|
|
83
|
+
overflow: 'auto',
|
|
84
|
+
boxSizing: 'border-box',
|
|
85
|
+
justifyContent: {
|
|
86
|
+
isEmpty: 'center'
|
|
87
|
+
},
|
|
88
|
+
alignItems: {
|
|
89
|
+
isEmpty: 'center'
|
|
90
|
+
},
|
|
91
|
+
height: {
|
|
92
|
+
isEmpty: 'full'
|
|
93
|
+
},
|
|
94
|
+
'--indent': {
|
|
95
|
+
type: 'width',
|
|
96
|
+
value: 16
|
|
97
|
+
}
|
|
98
|
+
}, getAllowedOverrides({height: true}));
|
|
99
|
+
|
|
100
|
+
function TreeView(props: TreeViewProps, ref: DOMRef<HTMLDivElement>) {
|
|
101
|
+
let {children, isDetached, isEmphasized} = props;
|
|
102
|
+
|
|
103
|
+
let renderer;
|
|
104
|
+
if (typeof children === 'function') {
|
|
105
|
+
renderer = children;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
let domRef = useDOMRef(ref);
|
|
109
|
+
|
|
110
|
+
let layout = useMemo(() => {
|
|
111
|
+
return new UNSTABLE_ListLayout({
|
|
112
|
+
rowHeight: isDetached ? 42 : 40
|
|
113
|
+
});
|
|
114
|
+
}, [isDetached]);
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<UNSTABLE_Virtualizer layout={layout}>
|
|
118
|
+
<TreeRendererContext.Provider value={{renderer}}>
|
|
119
|
+
<InternalTreeContext.Provider value={{isDetached, isEmphasized}}>
|
|
120
|
+
<UNSTABLE_Tree
|
|
121
|
+
{...props}
|
|
122
|
+
className={({isEmpty}) => tree({isEmpty, isDetached}, props.styles)}
|
|
123
|
+
selectionBehavior="toggle"
|
|
124
|
+
ref={domRef}>
|
|
125
|
+
{props.children}
|
|
126
|
+
</UNSTABLE_Tree>
|
|
127
|
+
</InternalTreeContext.Provider>
|
|
128
|
+
</TreeRendererContext.Provider>
|
|
129
|
+
</UNSTABLE_Virtualizer>
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const selectedBackground = lightDark(colorMix('gray-25', 'informative-900', 10), colorMix('gray-25', 'informative-700', 10));
|
|
134
|
+
const selectedActiveBackground = lightDark(colorMix('gray-25', 'informative-900', 15), colorMix('gray-25', 'informative-700', 15));
|
|
135
|
+
|
|
136
|
+
const rowBackgroundColor = {
|
|
137
|
+
default: '--s2-container-bg',
|
|
138
|
+
isFocusVisibleWithin: colorMix('gray-25', 'gray-900', 7),
|
|
139
|
+
isHovered: colorMix('gray-25', 'gray-900', 7),
|
|
140
|
+
isPressed: colorMix('gray-25', 'gray-900', 10),
|
|
141
|
+
isSelected: {
|
|
142
|
+
default: colorMix('gray-25', 'gray-900', 7),
|
|
143
|
+
isEmphasized: selectedBackground,
|
|
144
|
+
isFocusVisibleWithin: {
|
|
145
|
+
default: colorMix('gray-25', 'gray-900', 10),
|
|
146
|
+
isEmphasized: selectedActiveBackground
|
|
147
|
+
},
|
|
148
|
+
isHovered: {
|
|
149
|
+
default: colorMix('gray-25', 'gray-900', 10),
|
|
150
|
+
isEmphasized: selectedActiveBackground
|
|
151
|
+
},
|
|
152
|
+
isPressed: {
|
|
153
|
+
default: colorMix('gray-25', 'gray-900', 10),
|
|
154
|
+
isEmphasized: selectedActiveBackground
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
forcedColors: {
|
|
158
|
+
default: 'Background'
|
|
159
|
+
}
|
|
160
|
+
} as const;
|
|
161
|
+
|
|
162
|
+
const treeRow = style({
|
|
163
|
+
position: 'relative',
|
|
164
|
+
display: 'flex',
|
|
165
|
+
height: 40,
|
|
166
|
+
width: 'full',
|
|
167
|
+
boxSizing: 'border-box',
|
|
168
|
+
font: 'ui',
|
|
169
|
+
color: 'body',
|
|
170
|
+
outlineStyle: 'none',
|
|
171
|
+
cursor: {
|
|
172
|
+
default: 'default',
|
|
173
|
+
isLink: 'pointer'
|
|
174
|
+
},
|
|
175
|
+
'--rowBackgroundColor': {
|
|
176
|
+
type: 'backgroundColor',
|
|
177
|
+
value: rowBackgroundColor
|
|
178
|
+
},
|
|
179
|
+
'--rowFocusIndicatorColor': {
|
|
180
|
+
type: 'outlineColor',
|
|
181
|
+
value: {
|
|
182
|
+
default: 'focus-ring',
|
|
183
|
+
forcedColors: 'Highlight'
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
const treeCellGrid = style({
|
|
190
|
+
display: 'grid',
|
|
191
|
+
width: 'full',
|
|
192
|
+
alignContent: 'center',
|
|
193
|
+
alignItems: 'center',
|
|
194
|
+
gridTemplateColumns: ['minmax(0, auto)', 'minmax(0, auto)', 'minmax(0, auto)', 40, 'minmax(0, auto)', '1fr', 'minmax(0, auto)', 'auto'],
|
|
195
|
+
gridTemplateRows: '1fr',
|
|
196
|
+
gridTemplateAreas: [
|
|
197
|
+
'drag-handle checkbox level-padding expand-button icon content actions actionmenu'
|
|
198
|
+
],
|
|
199
|
+
backgroundColor: '--rowBackgroundColor',
|
|
200
|
+
paddingEnd: 4, // account for any focus rings on the last item in the cell
|
|
201
|
+
color: {
|
|
202
|
+
isDisabled: {
|
|
203
|
+
default: 'gray-400',
|
|
204
|
+
forcedColors: 'GrayText'
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
'--rowSelectedBorderColor': {
|
|
208
|
+
type: 'outlineColor',
|
|
209
|
+
value: {
|
|
210
|
+
default: 'gray-800',
|
|
211
|
+
isFocusVisible: 'focus-ring',
|
|
212
|
+
forcedColors: 'Highlight'
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
'--rowForcedFocusBorderColor': {
|
|
216
|
+
type: 'outlineColor',
|
|
217
|
+
value: {
|
|
218
|
+
default: 'focus-ring',
|
|
219
|
+
forcedColors: 'Highlight'
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
borderTopColor: {
|
|
223
|
+
default: 'transparent',
|
|
224
|
+
isSelected: {
|
|
225
|
+
isFirst: 'transparent'
|
|
226
|
+
},
|
|
227
|
+
isDetached: {
|
|
228
|
+
default: 'transparent',
|
|
229
|
+
isSelected: '--rowSelectedBorderColor'
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
borderInlineEndColor: {
|
|
233
|
+
default: 'transparent',
|
|
234
|
+
isSelected: 'transparent',
|
|
235
|
+
isDetached: {
|
|
236
|
+
default: 'transparent',
|
|
237
|
+
isSelected: '--rowSelectedBorderColor'
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
borderBottomColor: {
|
|
241
|
+
default: 'transparent',
|
|
242
|
+
isSelected: 'transparent',
|
|
243
|
+
isNextSelected: 'transparent',
|
|
244
|
+
isNextFocused: 'transparent',
|
|
245
|
+
isDetached: {
|
|
246
|
+
default: 'transparent',
|
|
247
|
+
isSelected: '--rowSelectedBorderColor'
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
borderInlineStartColor: {
|
|
251
|
+
default: 'transparent',
|
|
252
|
+
isSelected: 'transparent',
|
|
253
|
+
isDetached: {
|
|
254
|
+
default: 'transparent',
|
|
255
|
+
isSelected: '--rowSelectedBorderColor'
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
borderTopWidth: {
|
|
259
|
+
default: 0,
|
|
260
|
+
isFirst: {
|
|
261
|
+
default: 1,
|
|
262
|
+
forcedColors: 0
|
|
263
|
+
},
|
|
264
|
+
isDetached: 1
|
|
265
|
+
},
|
|
266
|
+
borderBottomWidth: {
|
|
267
|
+
default: 0,
|
|
268
|
+
isDetached: 1
|
|
269
|
+
},
|
|
270
|
+
borderStartWidth: {
|
|
271
|
+
default: 0,
|
|
272
|
+
isDetached: 1
|
|
273
|
+
},
|
|
274
|
+
borderEndWidth: {
|
|
275
|
+
default: 0,
|
|
276
|
+
isDetached: 1
|
|
277
|
+
},
|
|
278
|
+
borderRadius: {
|
|
279
|
+
isDetached: 'default'
|
|
280
|
+
},
|
|
281
|
+
borderStyle: 'solid'
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
const treeCheckbox = style({
|
|
285
|
+
gridArea: 'checkbox',
|
|
286
|
+
marginStart: 12,
|
|
287
|
+
marginEnd: 0,
|
|
288
|
+
paddingEnd: 0
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
const treeIcon = style({
|
|
292
|
+
gridArea: 'icon',
|
|
293
|
+
marginEnd: 'text-to-visual',
|
|
294
|
+
'--iconPrimary': {
|
|
295
|
+
type: 'fill',
|
|
296
|
+
value: 'currentColor'
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
const treeContent = style({
|
|
301
|
+
gridArea: 'content',
|
|
302
|
+
textOverflow: 'ellipsis',
|
|
303
|
+
whiteSpace: 'nowrap',
|
|
304
|
+
overflow: 'hidden'
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
const treeActions = style({
|
|
308
|
+
gridArea: 'actions',
|
|
309
|
+
flexGrow: 0,
|
|
310
|
+
flexShrink: 0,
|
|
311
|
+
/* TODO: I made this one up, confirm desired behavior. These paddings are to make sure the action group has enough padding for the focus ring */
|
|
312
|
+
marginStart: 2,
|
|
313
|
+
marginEnd: 4
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
const treeActionMenu = style({
|
|
317
|
+
gridArea: 'actionmenu'
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
const cellFocus = {
|
|
321
|
+
outlineStyle: {
|
|
322
|
+
default: 'none',
|
|
323
|
+
isFocusVisible: 'solid'
|
|
324
|
+
},
|
|
325
|
+
outlineOffset: -2,
|
|
326
|
+
outlineWidth: 2,
|
|
327
|
+
outlineColor: 'focus-ring',
|
|
328
|
+
borderRadius: '[6px]'
|
|
329
|
+
} as const;
|
|
330
|
+
|
|
331
|
+
const treeRowFocusIndicator = raw(`
|
|
332
|
+
&:before {
|
|
333
|
+
content: "";
|
|
334
|
+
display: inline-block;
|
|
335
|
+
position: sticky;
|
|
336
|
+
inset-inline-start: 0;
|
|
337
|
+
width: 3px;
|
|
338
|
+
height: 100%;
|
|
339
|
+
margin-inline-end: -3px;
|
|
340
|
+
margin-block-end: 1px;
|
|
341
|
+
z-index: 3;
|
|
342
|
+
background-color: var(--rowFocusIndicatorColor);
|
|
343
|
+
}`
|
|
344
|
+
);
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
export const TreeViewItem = <T extends object>(props: TreeViewItemProps<T>) => {
|
|
348
|
+
let {
|
|
349
|
+
children,
|
|
350
|
+
childItems,
|
|
351
|
+
hasChildItems,
|
|
352
|
+
href
|
|
353
|
+
} = props;
|
|
354
|
+
|
|
355
|
+
let content;
|
|
356
|
+
let nestedRows;
|
|
357
|
+
let {renderer} = useTreeRendererContext();
|
|
358
|
+
let {isDetached, isEmphasized} = useContext(InternalTreeContext);
|
|
359
|
+
|
|
360
|
+
if (typeof children === 'string') {
|
|
361
|
+
content = <Text>{children}</Text>;
|
|
362
|
+
} else {
|
|
363
|
+
content = [];
|
|
364
|
+
nestedRows = [];
|
|
365
|
+
React.Children.forEach(children, node => {
|
|
366
|
+
if (isValidElement(node) && node.type === TreeViewItem) {
|
|
367
|
+
nestedRows.push(node);
|
|
368
|
+
} else {
|
|
369
|
+
content.push(node);
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (childItems != null && renderer) {
|
|
375
|
+
nestedRows = (
|
|
376
|
+
<Collection items={childItems}>
|
|
377
|
+
{renderer}
|
|
378
|
+
</Collection>
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
return (
|
|
383
|
+
<UNSTABLE_TreeItem
|
|
384
|
+
{...props}
|
|
385
|
+
className={(renderProps) => treeRow({...renderProps, isLink: !!href, isEmphasized}) + (renderProps.isFocusVisible && !isDetached ? ' ' + treeRowFocusIndicator : '')}>
|
|
386
|
+
<UNSTABLE_TreeItemContent>
|
|
387
|
+
{({isExpanded, hasChildRows, selectionMode, selectionBehavior, isDisabled, isFocusVisible, isSelected, id, state}) => {
|
|
388
|
+
let isNextSelected = false;
|
|
389
|
+
let isNextFocused = false;
|
|
390
|
+
let keyAfter = state.collection.getKeyAfter(id);
|
|
391
|
+
if (keyAfter != null) {
|
|
392
|
+
isNextSelected = state.selectionManager.isSelected(keyAfter);
|
|
393
|
+
}
|
|
394
|
+
let isFirst = state.collection.getFirstKey() === id;
|
|
395
|
+
return (
|
|
396
|
+
<div className={treeCellGrid({isDisabled, isNextSelected, isSelected, isFirst, isNextFocused, isDetached})}>
|
|
397
|
+
{selectionMode !== 'none' && selectionBehavior === 'toggle' && (
|
|
398
|
+
// TODO: add transition?
|
|
399
|
+
<div className={treeCheckbox}>
|
|
400
|
+
<Checkbox
|
|
401
|
+
isEmphasized={isEmphasized}
|
|
402
|
+
slot="selection" />
|
|
403
|
+
</div>
|
|
404
|
+
)}
|
|
405
|
+
<div
|
|
406
|
+
className={style({
|
|
407
|
+
gridArea: 'level-padding',
|
|
408
|
+
width: '[calc(calc(var(--tree-item-level, 0) - 1) * var(--indent))]'
|
|
409
|
+
})} />
|
|
410
|
+
{/* 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 */}
|
|
411
|
+
{(hasChildRows || hasChildItems) && <ExpandableRowChevron isDisabled={isDisabled} isExpanded={isExpanded} />}
|
|
412
|
+
<Provider
|
|
413
|
+
values={[
|
|
414
|
+
[TextContext, {styles: treeContent}],
|
|
415
|
+
[IconContext, {
|
|
416
|
+
render: centerBaseline({slot: 'icon', styles: treeIcon}),
|
|
417
|
+
styles: style({size: fontRelative(20), flexShrink: 0})
|
|
418
|
+
}],
|
|
419
|
+
[ActionButtonGroupContext, {styles: treeActions}],
|
|
420
|
+
[ActionMenuContext, {styles: treeActionMenu, isQuiet: true}]
|
|
421
|
+
]}>
|
|
422
|
+
{content}
|
|
423
|
+
</Provider>
|
|
424
|
+
{isFocusVisible && isDetached && <div role="presentation" className={style({...cellFocus, position: 'absolute', inset: 0})({isFocusVisible: true})} />}
|
|
425
|
+
</div>
|
|
426
|
+
);
|
|
427
|
+
}}
|
|
428
|
+
</UNSTABLE_TreeItemContent>
|
|
429
|
+
{nestedRows}
|
|
430
|
+
</UNSTABLE_TreeItem>
|
|
431
|
+
);
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
interface ExpandableRowChevronProps {
|
|
435
|
+
isExpanded?: boolean,
|
|
436
|
+
isDisabled?: boolean,
|
|
437
|
+
isRTL?: boolean
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const expandButton = style<ExpandableRowChevronProps>({
|
|
441
|
+
gridArea: 'expand-button',
|
|
442
|
+
height: 'full',
|
|
443
|
+
aspectRatio: 'square',
|
|
444
|
+
display: 'flex',
|
|
445
|
+
flexWrap: 'wrap',
|
|
446
|
+
alignContent: 'center',
|
|
447
|
+
justifyContent: 'center',
|
|
448
|
+
outlineStyle: 'none',
|
|
449
|
+
cursor: 'default',
|
|
450
|
+
transform: {
|
|
451
|
+
isExpanded: {
|
|
452
|
+
default: 'rotate(90deg)',
|
|
453
|
+
isRTL: 'rotate(-90deg)'
|
|
454
|
+
}
|
|
455
|
+
},
|
|
456
|
+
transition: 'default',
|
|
457
|
+
backgroundColor: 'transparent',
|
|
458
|
+
borderStyle: 'none'
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
function ExpandableRowChevron(props: ExpandableRowChevronProps) {
|
|
462
|
+
let expandButtonRef = useRef<HTMLButtonElement>(null);
|
|
463
|
+
let [fullProps, ref] = useContextProps({...props, slot: 'chevron'}, expandButtonRef, ButtonContext);
|
|
464
|
+
let {isExpanded, isDisabled} = fullProps;
|
|
465
|
+
let {direction} = useLocale();
|
|
466
|
+
|
|
467
|
+
return (
|
|
468
|
+
<Button
|
|
469
|
+
{...props}
|
|
470
|
+
ref={ref}
|
|
471
|
+
slot="chevron"
|
|
472
|
+
// Override tabindex so that grid keyboard nav skips over it. Needs -1 so android talkback can actually "focus" it
|
|
473
|
+
excludeFromTabOrder={isAndroid() && !isDisabled}
|
|
474
|
+
preventFocusOnPress
|
|
475
|
+
className={renderProps => expandButton({...renderProps, isExpanded, isRTL: direction === 'rtl'})}>
|
|
476
|
+
<Chevron
|
|
477
|
+
className={style({
|
|
478
|
+
scale: {
|
|
479
|
+
direction: {
|
|
480
|
+
ltr: '1',
|
|
481
|
+
rtl: '-1'
|
|
482
|
+
}
|
|
483
|
+
},
|
|
484
|
+
'--iconPrimary': {
|
|
485
|
+
type: 'fill',
|
|
486
|
+
value: 'currentColor'
|
|
487
|
+
}
|
|
488
|
+
})({direction})} />
|
|
489
|
+
</Button>
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* A tree view provides users with a way to navigate nested hierarchical information.
|
|
495
|
+
*/
|
|
496
|
+
const _TreeView = forwardRef(TreeView);
|
|
497
|
+
export {_TreeView as TreeView};
|
package/src/index.ts
CHANGED
|
@@ -76,6 +76,7 @@ export {TextArea, TextField, TextAreaContext, TextFieldContext} from './TextFiel
|
|
|
76
76
|
export {ToggleButton, ToggleButtonContext} from './ToggleButton';
|
|
77
77
|
export {ToggleButtonGroup, ToggleButtonGroupContext} from './ToggleButtonGroup';
|
|
78
78
|
export {Tooltip, TooltipTrigger} from './Tooltip';
|
|
79
|
+
export {TreeView, TreeViewItem} from './TreeView';
|
|
79
80
|
|
|
80
81
|
export {pressScale} from './pressScale';
|
|
81
82
|
|
|
@@ -144,4 +145,5 @@ export type {TextFieldProps, TextAreaProps} from './TextField';
|
|
|
144
145
|
export type {ToggleButtonProps} from './ToggleButton';
|
|
145
146
|
export type {ToggleButtonGroupProps} from './ToggleButtonGroup';
|
|
146
147
|
export type {TooltipProps} from './Tooltip';
|
|
148
|
+
export type {TreeViewProps, TreeViewItemProps} from './TreeView';
|
|
147
149
|
export type {FileTriggerProps, TooltipTriggerComponentProps as TooltipTriggerProps} from 'react-aria-components';
|
|
@@ -40,7 +40,7 @@ describe('style-macro', () => {
|
|
|
40
40
|
"@layer _.a, _.b, _.c;
|
|
41
41
|
|
|
42
42
|
@layer _.b {
|
|
43
|
-
.
|
|
43
|
+
.D-13alit4c {
|
|
44
44
|
&:first-child {
|
|
45
45
|
margin-top: 0.25rem;
|
|
46
46
|
}
|
|
@@ -49,7 +49,7 @@ describe('style-macro', () => {
|
|
|
49
49
|
|
|
50
50
|
@layer _.c.e {
|
|
51
51
|
@media (min-width: 1024px) {
|
|
52
|
-
.
|
|
52
|
+
.D-13alit4ed {
|
|
53
53
|
&:first-child {
|
|
54
54
|
margin-top: 0.5rem;
|
|
55
55
|
}
|
|
@@ -59,7 +59,7 @@ describe('style-macro', () => {
|
|
|
59
59
|
|
|
60
60
|
"
|
|
61
61
|
`);
|
|
62
|
-
expect(js).toMatchInlineSnapshot('"
|
|
62
|
+
expect(js).toMatchInlineSnapshot('" D-13alit4c D-13alit4ed"');
|
|
63
63
|
});
|
|
64
64
|
|
|
65
65
|
it('should support self references', () => {
|
|
@@ -73,48 +73,48 @@ describe('style-macro', () => {
|
|
|
73
73
|
"@layer _.a, _.b;
|
|
74
74
|
|
|
75
75
|
@layer _.a {
|
|
76
|
-
.
|
|
76
|
+
.tc {
|
|
77
77
|
border-top-width: 2px;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
|
|
81
|
-
.
|
|
81
|
+
.uc {
|
|
82
82
|
border-bottom-width: 2px;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
|
|
86
|
-
.
|
|
87
|
-
border-inline-start-width: var(--
|
|
86
|
+
.r-375tox {
|
|
87
|
+
border-inline-start-width: var(--r);
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
|
|
91
|
-
.
|
|
91
|
+
.sc {
|
|
92
92
|
border-inline-end-width: 2px;
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
|
|
96
|
-
.
|
|
97
|
-
padding-inline-start: var(--
|
|
96
|
+
.F-375tnp {
|
|
97
|
+
padding-inline-start: var(--F);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
|
|
101
|
-
.
|
|
102
|
-
padding-inline-end: calc(var(--
|
|
101
|
+
.GI {
|
|
102
|
+
padding-inline-end: calc(var(--j, var(--n)) * 3 / 8);
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
|
|
106
|
-
.
|
|
107
|
-
width: calc(200px - var(--
|
|
106
|
+
.k-4s570k {
|
|
107
|
+
width: calc(200px - var(--r) - var(--F));
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
|
|
111
|
-
.-
|
|
112
|
-
--
|
|
111
|
+
.-_375tox_r-c {
|
|
112
|
+
--r: 2px;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
|
|
116
|
-
.-
|
|
117
|
-
--
|
|
116
|
+
.-_375tnp_F-I {
|
|
117
|
+
--F: calc(var(--j, var(--n)) * 3 / 8);
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
|
|
@@ -669,6 +669,16 @@ const $7dddb03c6ef7d79c$var$borderWidth = {
|
|
|
669
669
|
2: "2px",
|
|
670
670
|
4: "4px"
|
|
671
671
|
};
|
|
672
|
+
const $7dddb03c6ef7d79c$var$borderColor = (0, $b3643cb9d2948e30$exports.createColorProperty)({
|
|
673
|
+
...$7dddb03c6ef7d79c$var$color,
|
|
674
|
+
negative: {
|
|
675
|
+
default: "light-dark(rgb(215, 50, 32), rgb(252, 67, 46))",
|
|
676
|
+
isHovered: "light-dark(rgb(183, 40, 24), rgb(255, 103, 86))",
|
|
677
|
+
isFocusVisible: "light-dark(rgb(183, 40, 24), rgb(255, 103, 86))",
|
|
678
|
+
isPressed: "light-dark(rgb(156, 33, 19), rgb(255, 134, 120))"
|
|
679
|
+
},
|
|
680
|
+
disabled: "light-dark(rgb(218, 218, 218), rgb(57, 57, 57))"
|
|
681
|
+
});
|
|
672
682
|
const $7dddb03c6ef7d79c$var$radius = {
|
|
673
683
|
none: "0px",
|
|
674
684
|
sm: $7dddb03c6ef7d79c$var$pxToRem("4px"),
|
|
@@ -1043,16 +1053,6 @@ const $7dddb03c6ef7d79c$export$1d567c320f4763bc = (0, $b3643cb9d2948e30$exports.
|
|
|
1043
1053
|
pasteboard: "light-dark(rgb(233, 233, 233), rgb(17, 17, 17))",
|
|
1044
1054
|
elevated: "light-dark(rgb(255, 255, 255), rgb(34, 34, 34))"
|
|
1045
1055
|
}),
|
|
1046
|
-
borderColor: (0, $b3643cb9d2948e30$exports.createColorProperty)({
|
|
1047
|
-
...$7dddb03c6ef7d79c$var$color,
|
|
1048
|
-
negative: {
|
|
1049
|
-
default: "light-dark(rgb(215, 50, 32), rgb(252, 67, 46))",
|
|
1050
|
-
isHovered: "light-dark(rgb(183, 40, 24), rgb(255, 103, 86))",
|
|
1051
|
-
isFocusVisible: "light-dark(rgb(183, 40, 24), rgb(255, 103, 86))",
|
|
1052
|
-
isPressed: "light-dark(rgb(156, 33, 19), rgb(255, 134, 120))"
|
|
1053
|
-
},
|
|
1054
|
-
disabled: "light-dark(rgb(218, 218, 218), rgb(57, 57, 57))"
|
|
1055
|
-
}),
|
|
1056
1056
|
outlineColor: (0, $b3643cb9d2948e30$exports.createColorProperty)({
|
|
1057
1057
|
...$7dddb03c6ef7d79c$var$color,
|
|
1058
1058
|
'focus-ring': {
|
|
@@ -1125,6 +1125,10 @@ const $7dddb03c6ef7d79c$export$1d567c320f4763bc = (0, $b3643cb9d2948e30$exports.
|
|
|
1125
1125
|
borderEndWidth: (0, $b3643cb9d2948e30$exports.createRenamedProperty)('borderInlineEndWidth', $7dddb03c6ef7d79c$var$borderWidth),
|
|
1126
1126
|
borderTopWidth: $7dddb03c6ef7d79c$var$borderWidth,
|
|
1127
1127
|
borderBottomWidth: $7dddb03c6ef7d79c$var$borderWidth,
|
|
1128
|
+
borderInlineStartColor: $7dddb03c6ef7d79c$var$borderColor,
|
|
1129
|
+
borderInlineEndColor: $7dddb03c6ef7d79c$var$borderColor,
|
|
1130
|
+
borderTopColor: $7dddb03c6ef7d79c$var$borderColor,
|
|
1131
|
+
borderBottomColor: $7dddb03c6ef7d79c$var$borderColor,
|
|
1128
1132
|
borderStyle: [
|
|
1129
1133
|
'solid',
|
|
1130
1134
|
'dashed',
|
|
@@ -1919,6 +1923,12 @@ const $7dddb03c6ef7d79c$export$1d567c320f4763bc = (0, $b3643cb9d2948e30$exports.
|
|
|
1919
1923
|
'borderStartWidth',
|
|
1920
1924
|
'borderEndWidth'
|
|
1921
1925
|
],
|
|
1926
|
+
borderColor: [
|
|
1927
|
+
'borderTopColor',
|
|
1928
|
+
'borderBottomColor',
|
|
1929
|
+
'borderInlineStartColor',
|
|
1930
|
+
'borderInlineEndColor'
|
|
1931
|
+
],
|
|
1922
1932
|
borderXWidth: [
|
|
1923
1933
|
'borderStartWidth',
|
|
1924
1934
|
'borderEndWidth'
|