Skip to content

Commit 08ab15b

Browse files
committed
Improve drag target z-indexing and visibiility
1 parent 2c8c46a commit 08ab15b

File tree

8 files changed

+64
-75
lines changed

8 files changed

+64
-75
lines changed

demo/src/_imports.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
*/
44

55
/* Installed package */
6-
export * from 'json-edit-react'
6+
// export * from 'json-edit-react'
77

88
/* Local src */
9-
// export * from './json-edit-react/src'
9+
export * from './json-edit-react/src'
1010

1111
/* Compiled local package */
1212
// export * from './package/build'

src/ButtonPanels.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,7 @@ export const EditButtons: React.FC<EditButtonProps> = ({
7171
}
7272

7373
return (
74-
<div
75-
className="jer-edit-buttons"
76-
style={{ opacity: isAdding ? 1 : undefined, zIndex: path.length + 1 }}
77-
>
74+
<div className="jer-edit-buttons" style={{ opacity: isAdding ? 1 : undefined }}>
7875
{enableClipboard && (
7976
<div onClick={handleCopy} className="jer-copy-pulse">
8077
<Icon name="copy" nodeData={nodeData} />
@@ -138,7 +135,7 @@ export const InputButtons: React.FC<{
138135
nodeData: NodeData
139136
}> = ({ onOk, onCancel, nodeData }) => {
140137
return (
141-
<div className="jer-confirm-buttons" style={{ zIndex: nodeData.path.length + 1 }}>
138+
<div className="jer-confirm-buttons">
142139
<div onClick={onOk}>
143140
<Icon name="ok" nodeData={nodeData} />
144141
</div>

src/CollectionNode.tsx

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,7 @@ export const CollectionNode: React.FC<CollectionNodeProps> = (props) => {
6868
} = useCommon({ props, collapsed })
6969

7070
const { dragSourceProps, getDropTargetProps, BottomDropTarget, DropTargetPadding } = useDragNDrop(
71-
{
72-
canDragOnto,
73-
path,
74-
nodeData,
75-
onMove,
76-
onError,
77-
translate,
78-
}
71+
{ canDrag, canDragOnto, path, nodeData, onMove, onError, translate }
7972
)
8073

8174
// This allows us to not render the children on load if they're hidden (which
@@ -390,9 +383,8 @@ export const CollectionNode: React.FC<CollectionNodeProps> = (props) => {
390383
marginLeft: `${path.length === 0 ? 0 : indent / 2}em`,
391384
...getStyles('collection', nodeData),
392385
position: 'relative',
393-
zIndex: path.length,
394386
}}
395-
draggable={canDrag && currentlyEditingElement === null}
387+
draggable={canDrag}
396388
{...dragSourceProps}
397389
{...getDropTargetProps('above')}
398390
>

src/ValueNodeWrapper.tsx

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,7 @@ export const ValueNodeWrapper: React.FC<ValueNodeProps> = (props) => {
6868
} = useCommon({ props })
6969

7070
const { dragSourceProps, getDropTargetProps, BottomDropTarget, DropTargetPadding } = useDragNDrop(
71-
{
72-
canDragOnto,
73-
path,
74-
nodeData,
75-
onMove,
76-
onError,
77-
translate,
78-
}
71+
{ canDrag, canDragOnto, path, nodeData, onMove, onError, translate }
7972
)
8073

8174
const customNodeData = getCustomNode(customNodeDefinitions, nodeData)
@@ -251,9 +244,8 @@ export const ValueNodeWrapper: React.FC<ValueNodeProps> = (props) => {
251244
style={{
252245
marginLeft: `${indent / 2}em`,
253246
position: 'relative',
254-
zIndex: path.length + 1,
255247
}}
256-
draggable={canDrag && currentlyEditingElement === null}
248+
draggable={canDrag}
257249
{...dragSourceProps}
258250
{...getDropTargetProps('above')}
259251
>
@@ -313,7 +305,7 @@ export const ValueNodeWrapper: React.FC<ValueNodeProps> = (props) => {
313305
)
314306
)}
315307
{showTypeSelector && (
316-
<div className="jer-select" style={{ zIndex: path.length + 1 }}>
308+
<div className="jer-select">
317309
<select
318310
name={`${name}-type-select`}
319311
className="jer-type-select"

src/ValueNodes.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,6 @@ export const BooleanValue: React.FC<InputProps & { value: boolean }> = ({
157157
name={toPathString(path)}
158158
checked={value}
159159
onChange={() => setValue(!value)}
160-
style={{ zIndex: path.length + 2 }}
161160
/>
162161
) : (
163162
<span

src/style.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ select:focus + .focus {
8383
}
8484

8585
.jer-editor-container {
86+
position: relative;
8687
font-size: 16px;
8788
line-height: 1;
8889
padding: 1em;

src/useCommon.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ export const useCommon = ({ props, collapsed }: CommonProps) => {
4646
const canEdit = useMemo(() => !restrictEditFilter(nodeData), [nodeData])
4747
const canDelete = useMemo(() => !restrictDeleteFilter(nodeData), [nodeData])
4848
const canAdd = useMemo(() => !restrictAddFilter(nodeData), [nodeData])
49-
const canDrag = useMemo(() => !restrictDragFilter(nodeData) && canDelete, [nodeData])
49+
const canDrag = useMemo(
50+
() => !restrictDragFilter(nodeData) && canDelete && currentlyEditingElement === null,
51+
[nodeData]
52+
)
5053

5154
const showError = (errorString: ErrorString) => {
5255
if (showErrorMessages) {

src/useDragNDrop.tsx

Lines changed: 50 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
import { type TranslateFunction } from './localisation'
1414

1515
interface DnDProps {
16+
canDrag: boolean
1617
canDragOnto: boolean
1718
path: CollectionKey[]
1819
nodeData: NodeData
@@ -22,6 +23,7 @@ interface DnDProps {
2223
}
2324

2425
export const useDragNDrop = ({
26+
canDrag,
2527
canDragOnto,
2628
path,
2729
nodeData,
@@ -30,14 +32,15 @@ export const useDragNDrop = ({
3032
translate,
3133
}: DnDProps) => {
3234
const { getStyles } = useTheme()
33-
const { dragSource, setDragSource } = useTreeState()
35+
const { currentlyEditingElement, dragSource, setDragSource } = useTreeState()
3436
const [isDragTarget, setIsDragTarget] = useState<Position | false>(false)
3537

3638
const pathString = toPathString(path)
3739

3840
// Props added to items being dragged
39-
const dragSourceProps = useMemo(
40-
() => ({
41+
const dragSourceProps = useMemo(() => {
42+
if (!canDrag) return {}
43+
return {
4144
onDragStart: (e: React.DragEvent) => {
4245
e.stopPropagation()
4346
setDragSource({ path, pathString })
@@ -46,57 +49,59 @@ export const useDragNDrop = ({
4649
e.stopPropagation()
4750
setDragSource({ path: null, pathString: null })
4851
},
49-
}),
50-
[]
51-
)
52+
}
53+
}, [canDrag])
5254

5355
// Props for the items being dropped onto
5456
const getDropTargetProps = useMemo(
55-
() => (position: Position) => ({
56-
onDragOver: (e: React.DragEvent) => {
57-
e.stopPropagation()
58-
e.preventDefault()
59-
},
60-
onDrop: (e: React.DragEvent) => {
61-
e.stopPropagation()
62-
if (!canDragOnto) return
63-
handleDrop(position)
64-
setDragSource({ path: null, pathString: null })
65-
setIsDragTarget(false)
66-
},
67-
onDragEnter: (e: React.DragEvent) => {
68-
e.stopPropagation()
69-
if (!canDragOnto) return
70-
if (!pathString.startsWith(dragSource.pathString ?? '')) {
71-
setIsDragTarget(position)
72-
}
73-
},
74-
onDragExit: (e: React.DragEvent) => {
75-
e.stopPropagation()
76-
if (!canDragOnto) return
77-
setIsDragTarget(false)
78-
},
79-
}),
80-
[dragSource]
57+
() => (position: Position) => {
58+
if (!canDragOnto) return {}
59+
return {
60+
onDragOver: (e: React.DragEvent) => {
61+
e.stopPropagation()
62+
e.preventDefault()
63+
},
64+
onDrop: (e: React.DragEvent) => {
65+
e.stopPropagation()
66+
handleDrop(position)
67+
setDragSource({ path: null, pathString: null })
68+
setIsDragTarget(false)
69+
},
70+
onDragEnter: (e: React.DragEvent) => {
71+
e.stopPropagation()
72+
if (!pathString.startsWith(dragSource.pathString ?? '')) {
73+
setIsDragTarget(position)
74+
}
75+
},
76+
onDragExit: (e: React.DragEvent) => {
77+
e.stopPropagation()
78+
setIsDragTarget(false)
79+
},
80+
}
81+
},
82+
[dragSource, canDragOnto]
8183
)
8284

8385
// A dummy component to allow us to detect when dragging onto the *bottom*
8486
// half of an element -- takes up exactly 50% its container height and is
8587
// locked to the bottom.
8688
const BottomDropTarget = useMemo(
87-
() => (
88-
<div
89-
style={{
90-
height: '50%',
91-
position: 'absolute',
92-
width: '100%',
93-
top: '50%',
94-
zIndex: path.length,
95-
}}
96-
{...getDropTargetProps('below')}
97-
></div>
98-
),
99-
[dragSource]
89+
() =>
90+
canDragOnto && dragSource.pathString !== null ? (
91+
<div
92+
className="jer-drop-target-bottom"
93+
style={{
94+
height: '50%',
95+
position: 'absolute',
96+
width: '100%',
97+
top: '50%',
98+
zIndex: path.length,
99+
// border: '1px dotted green',
100+
}}
101+
{...getDropTargetProps('below')}
102+
></div>
103+
) : null,
104+
[dragSource, canDragOnto]
100105
)
101106

102107
// "Padding" element displayed either above or below a node to indicate

0 commit comments

Comments
 (0)