@react-spectrum/list 3.0.0-rc.0 → 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/main.css +1 -1
- package/dist/main.js +9 -63
- package/dist/main.js.map +1 -1
- package/dist/module.js +9 -63
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +26 -26
- package/src/DragPreview.tsx +2 -3
- package/src/ListView.tsx +78 -122
- package/src/styles.css +9 -2
package/src/ListView.tsx
CHANGED
|
@@ -15,6 +15,7 @@ import type {DraggableCollectionState, DroppableCollectionState} from '@react-st
|
|
|
15
15
|
import {DragHooks, DropHooks} from '@react-spectrum/dnd';
|
|
16
16
|
import type {DroppableCollectionResult} from '@react-aria/dnd';
|
|
17
17
|
import {filterDOMProps, useLayoutEffect} from '@react-aria/utils';
|
|
18
|
+
import {FocusRing} from '@react-aria/focus';
|
|
18
19
|
import InsertionIndicator from './InsertionIndicator';
|
|
19
20
|
// @ts-ignore
|
|
20
21
|
import intlMessages from '../intl/*.json';
|
|
@@ -25,7 +26,6 @@ import {ListViewItem} from './ListViewItem';
|
|
|
25
26
|
import {mergeProps} from '@react-aria/utils';
|
|
26
27
|
import {ProgressCircle} from '@react-spectrum/progress';
|
|
27
28
|
import React, {Key, ReactElement, useContext, useMemo, useRef, useState} from 'react';
|
|
28
|
-
import {Rect} from '@react-stately/virtualizer';
|
|
29
29
|
import RootDropIndicator from './RootDropIndicator';
|
|
30
30
|
import {DragPreview as SpectrumDragPreview} from './DragPreview';
|
|
31
31
|
import {SpectrumListViewProps} from '@react-types/list';
|
|
@@ -144,53 +144,7 @@ function ListView<T extends object>(props: SpectrumListViewProps<T>, ref: DOMRef
|
|
|
144
144
|
});
|
|
145
145
|
droppableCollection = dropHooks.useDroppableCollection({
|
|
146
146
|
keyboardDelegate: layout,
|
|
147
|
-
|
|
148
|
-
let closest = null;
|
|
149
|
-
let closestDistance = Infinity;
|
|
150
|
-
let closestDir = null;
|
|
151
|
-
|
|
152
|
-
x += domRef.current.scrollLeft;
|
|
153
|
-
y += domRef.current.scrollTop;
|
|
154
|
-
|
|
155
|
-
let visible = layout.getVisibleLayoutInfos(new Rect(x - 50, y - 50, x + 50, y + 50));
|
|
156
|
-
|
|
157
|
-
for (let layoutInfo of visible) {
|
|
158
|
-
let r = layoutInfo.rect;
|
|
159
|
-
let points: [number, number, string][] = [
|
|
160
|
-
[r.x, r.y + 4, 'before'],
|
|
161
|
-
[r.maxX, r.y + 4, 'before'],
|
|
162
|
-
[r.x, r.maxY - 8, 'after'],
|
|
163
|
-
[r.maxX, r.maxY - 8, 'after']
|
|
164
|
-
];
|
|
165
|
-
|
|
166
|
-
for (let [px, py, dir] of points) {
|
|
167
|
-
let dx = px - x;
|
|
168
|
-
let dy = py - y;
|
|
169
|
-
let d = dx * dx + dy * dy;
|
|
170
|
-
if (d < closestDistance) {
|
|
171
|
-
closestDistance = d;
|
|
172
|
-
closest = layoutInfo;
|
|
173
|
-
closestDir = dir;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// TODO: Best way to implement only for when closest can be dropped on
|
|
178
|
-
// TODO: Figure out the typescript for this
|
|
179
|
-
// @ts-ignore
|
|
180
|
-
if (y >= r.y + 10 && y <= r.maxY - 10 && collection.getItem(closest.key).value.type === 'folder') {
|
|
181
|
-
closestDir = 'on';
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
let key = closest?.key;
|
|
186
|
-
if (key) {
|
|
187
|
-
return {
|
|
188
|
-
type: 'item',
|
|
189
|
-
key,
|
|
190
|
-
dropPosition: closestDir
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
}
|
|
147
|
+
dropTargetDelegate: layout
|
|
194
148
|
}, dropState, domRef);
|
|
195
149
|
|
|
196
150
|
isRootDropTarget = dropState.isDropTarget({type: 'root'});
|
|
@@ -226,82 +180,84 @@ function ListView<T extends object>(props: SpectrumListViewProps<T>, ref: DOMRef
|
|
|
226
180
|
|
|
227
181
|
return (
|
|
228
182
|
<ListViewContext.Provider value={{state, dragState, dropState, dragHooks, dropHooks, onAction, isListDraggable, isListDroppable, layout, loadingState}}>
|
|
229
|
-
<
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
{isListDroppable &&
|
|
269
|
-
<InsertionIndicator
|
|
270
|
-
key={`${item.key}-before`}
|
|
271
|
-
target={{key: item.key, type: 'item', dropPosition: 'before'}} />
|
|
272
|
-
}
|
|
273
|
-
<ListViewItem item={item} isEmphasized hasActions={!!onAction} />
|
|
274
|
-
{isListDroppable &&
|
|
275
|
-
<InsertionIndicator
|
|
276
|
-
key={`${item.key}-after`}
|
|
277
|
-
target={{key: item.key, type: 'item', dropPosition: 'after'}}
|
|
278
|
-
isPresentationOnly={collection.getKeyAfter(item.key) != null} />
|
|
183
|
+
<FocusRing focusRingClass={classNames(listStyles, 'focus-ring')}>
|
|
184
|
+
<Virtualizer
|
|
185
|
+
{...mergeProps(isListDroppable && droppableCollection?.collectionProps, gridProps)}
|
|
186
|
+
{...filterDOMProps(otherProps)}
|
|
187
|
+
{...gridProps}
|
|
188
|
+
{...styleProps}
|
|
189
|
+
isLoading={isLoading}
|
|
190
|
+
onLoadMore={onLoadMore}
|
|
191
|
+
ref={domRef}
|
|
192
|
+
focusedKey={focusedKey}
|
|
193
|
+
scrollDirection="vertical"
|
|
194
|
+
className={
|
|
195
|
+
classNames(
|
|
196
|
+
listStyles,
|
|
197
|
+
'react-spectrum-ListView',
|
|
198
|
+
`react-spectrum-ListView--${density}`,
|
|
199
|
+
'react-spectrum-ListView--emphasized',
|
|
200
|
+
{
|
|
201
|
+
'react-spectrum-ListView--quiet': isQuiet,
|
|
202
|
+
'react-spectrum-ListView--loadingMore': loadingState === 'loadingMore',
|
|
203
|
+
'react-spectrum-ListView--draggable': !!isListDraggable,
|
|
204
|
+
'react-spectrum-ListView--dropTarget': !!isRootDropTarget,
|
|
205
|
+
'react-spectrum-ListView--isVerticalScrollbarVisible': isVerticalScrollbarVisible,
|
|
206
|
+
'react-spectrum-ListView--isHorizontalScrollbarVisible': isHorizontalScrollbarVisible,
|
|
207
|
+
'react-spectrum-ListView--hasAnyChildren': hasAnyChildren,
|
|
208
|
+
'react-spectrum-ListView--wrap': overflowMode === 'wrap'
|
|
209
|
+
},
|
|
210
|
+
styleProps.className
|
|
211
|
+
)
|
|
212
|
+
}
|
|
213
|
+
layout={layout}
|
|
214
|
+
collection={collection}
|
|
215
|
+
transitionDuration={isLoading ? 160 : 220}>
|
|
216
|
+
{(type, item) => {
|
|
217
|
+
if (type === 'item') {
|
|
218
|
+
return (
|
|
219
|
+
<>
|
|
220
|
+
{isListDroppable && collection.getKeyBefore(item.key) == null &&
|
|
221
|
+
<RootDropIndicator key="root" />
|
|
279
222
|
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
}
|
|
223
|
+
{isListDroppable &&
|
|
224
|
+
<InsertionIndicator
|
|
225
|
+
key={`${item.key}-before`}
|
|
226
|
+
target={{key: item.key, type: 'item', dropPosition: 'before'}} />
|
|
227
|
+
}
|
|
228
|
+
<ListViewItem item={item} isEmphasized hasActions={!!onAction} />
|
|
229
|
+
{isListDroppable &&
|
|
230
|
+
<InsertionIndicator
|
|
231
|
+
key={`${item.key}-after`}
|
|
232
|
+
target={{key: item.key, type: 'item', dropPosition: 'after'}}
|
|
233
|
+
isPresentationOnly={collection.getKeyAfter(item.key) != null} />
|
|
234
|
+
}
|
|
235
|
+
</>
|
|
236
|
+
);
|
|
237
|
+
} else if (type === 'loader') {
|
|
238
|
+
return (
|
|
239
|
+
<CenteredWrapper>
|
|
240
|
+
<ProgressCircle
|
|
241
|
+
isIndeterminate
|
|
242
|
+
aria-label={collection.size > 0 ? stringFormatter.format('loadingMore') : stringFormatter.format('loading')} />
|
|
243
|
+
</CenteredWrapper>
|
|
244
|
+
);
|
|
245
|
+
} else if (type === 'placeholder') {
|
|
246
|
+
let emptyState = props.renderEmptyState ? props.renderEmptyState() : null;
|
|
247
|
+
if (emptyState == null) {
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
295
250
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
251
|
+
return (
|
|
252
|
+
<CenteredWrapper>
|
|
253
|
+
{emptyState}
|
|
254
|
+
</CenteredWrapper>
|
|
255
|
+
);
|
|
256
|
+
}
|
|
302
257
|
|
|
303
|
-
|
|
304
|
-
|
|
258
|
+
}}
|
|
259
|
+
</Virtualizer>
|
|
260
|
+
</FocusRing>
|
|
305
261
|
{DragPreview && isListDraggable &&
|
|
306
262
|
<DragPreview ref={preview}>
|
|
307
263
|
{() => {
|
|
@@ -338,7 +294,7 @@ function CenteredWrapper({children}) {
|
|
|
338
294
|
}
|
|
339
295
|
|
|
340
296
|
/**
|
|
341
|
-
*
|
|
297
|
+
* A ListView displays a list of interactive items, and allows a user to navigate, select, or perform an action.
|
|
342
298
|
*/
|
|
343
299
|
const _ListView = React.forwardRef(ListView) as <T>(props: SpectrumListViewProps<T> & {ref?: DOMRef<HTMLDivElement>}) => ReactElement;
|
|
344
300
|
export {_ListView as ListView};
|
package/src/styles.css
CHANGED
|
@@ -337,7 +337,7 @@
|
|
|
337
337
|
align-items: center;
|
|
338
338
|
justify-content: center;
|
|
339
339
|
|
|
340
|
-
> img
|
|
340
|
+
> img {
|
|
341
341
|
width: unset;
|
|
342
342
|
height: 100%;
|
|
343
343
|
}
|
|
@@ -403,7 +403,7 @@
|
|
|
403
403
|
grid-template-areas:
|
|
404
404
|
"thumbnail content . badge"
|
|
405
405
|
"thumbnail description . badge";
|
|
406
|
-
grid-template-columns: auto auto auto
|
|
406
|
+
grid-template-columns: auto auto 1fr auto;
|
|
407
407
|
}
|
|
408
408
|
|
|
409
409
|
.react-spectrum-ListViewItem-badge {
|
|
@@ -586,3 +586,10 @@
|
|
|
586
586
|
opacity: 0.01;
|
|
587
587
|
max-width: 0px;
|
|
588
588
|
}
|
|
589
|
+
|
|
590
|
+
.react-spectrum-ListView {
|
|
591
|
+
&:focus-ring {
|
|
592
|
+
border-color: var(--spectrum-global-color-blue-500);
|
|
593
|
+
box-shadow: inset 0 0 0 1px var(--spectrum-table-cell-border-color-key-focus);
|
|
594
|
+
}
|
|
595
|
+
}
|