@rpcbase/client 0.180.0 → 0.181.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/package.json +1 -1
- package/ui/LottiePlayer/index.js +1 -1
- package/ui/Tabs/index.js +158 -0
- package/ui/Tabs/tabs.scss +53 -0
- package/ui/helpers/stopEventPropagation.js +5 -0
- package/ui/helpers/useThrottledMeasure/index.js +49 -0
- package/ui/{withSuspense → helpers/withSuspense}/index.js +2 -4
- package/ui/sortable-hoc/AutoScroller.js +76 -0
- package/ui/sortable-hoc/DragHandle.js +31 -0
- package/ui/sortable-hoc/Manager.js +54 -0
- package/ui/sortable-hoc/README.md +1 -0
- package/ui/sortable-hoc/SortableContainer/defaultGetHelperDimensions.js +7 -0
- package/ui/sortable-hoc/SortableContainer/defaultShouldCancelStart.js +24 -0
- package/ui/sortable-hoc/SortableContainer/index.js +994 -0
- package/ui/sortable-hoc/SortableContainer/props.js +81 -0
- package/ui/sortable-hoc/SortableElement.js +111 -0
- package/ui/sortable-hoc/SortableHandle.js +45 -0
- package/ui/sortable-hoc/drag-handle.scss +14 -0
- package/ui/sortable-hoc/index.js +9 -0
- package/ui/sortable-hoc/utils.js +292 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/* @flow */
|
|
2
|
+
import PropTypes from "prop-types"
|
|
3
|
+
import invariant from "invariant"
|
|
4
|
+
|
|
5
|
+
import {KEYCODE} from "../utils"
|
|
6
|
+
import defaultGetHelperDimensions from "./defaultGetHelperDimensions"
|
|
7
|
+
import defaultShouldCancelStart from "./defaultShouldCancelStart"
|
|
8
|
+
|
|
9
|
+
export const propTypes = {
|
|
10
|
+
axis: PropTypes.oneOf(["x", "y", "xy"]),
|
|
11
|
+
contentWindow: PropTypes.any,
|
|
12
|
+
disableAutoscroll: PropTypes.bool,
|
|
13
|
+
distance: PropTypes.number,
|
|
14
|
+
getContainer: PropTypes.func,
|
|
15
|
+
getHelperDimensions: PropTypes.func,
|
|
16
|
+
helperClass: PropTypes.string,
|
|
17
|
+
helperContainer: PropTypes.oneOfType([
|
|
18
|
+
PropTypes.func,
|
|
19
|
+
typeof HTMLElement === "undefined" ? PropTypes.any : PropTypes.instanceOf(HTMLElement),
|
|
20
|
+
]),
|
|
21
|
+
hideSortableGhost: PropTypes.bool,
|
|
22
|
+
keyboardSortingTransitionDuration: PropTypes.number,
|
|
23
|
+
lockAxis: PropTypes.string,
|
|
24
|
+
lockOffset: PropTypes.oneOfType([
|
|
25
|
+
PropTypes.number,
|
|
26
|
+
PropTypes.string,
|
|
27
|
+
PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.string])),
|
|
28
|
+
]),
|
|
29
|
+
lockToContainerEdges: PropTypes.bool,
|
|
30
|
+
onSortEnd: PropTypes.func,
|
|
31
|
+
onSortMove: PropTypes.func,
|
|
32
|
+
onSortOver: PropTypes.func,
|
|
33
|
+
onSortStart: PropTypes.func,
|
|
34
|
+
pressDelay: PropTypes.number,
|
|
35
|
+
pressThreshold: PropTypes.number,
|
|
36
|
+
keyCodes: PropTypes.shape({
|
|
37
|
+
lift: PropTypes.arrayOf(PropTypes.number),
|
|
38
|
+
drop: PropTypes.arrayOf(PropTypes.number),
|
|
39
|
+
cancel: PropTypes.arrayOf(PropTypes.number),
|
|
40
|
+
up: PropTypes.arrayOf(PropTypes.number),
|
|
41
|
+
down: PropTypes.arrayOf(PropTypes.number),
|
|
42
|
+
}),
|
|
43
|
+
shouldCancelStart: PropTypes.func,
|
|
44
|
+
transitionDuration: PropTypes.number,
|
|
45
|
+
updateBeforeSortStart: PropTypes.func,
|
|
46
|
+
useDragHandle: PropTypes.bool,
|
|
47
|
+
useWindowAsScrollContainer: PropTypes.bool,
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const defaultKeyCodes = {
|
|
51
|
+
lift: [KEYCODE.SPACE],
|
|
52
|
+
drop: [KEYCODE.SPACE],
|
|
53
|
+
cancel: [KEYCODE.ESC],
|
|
54
|
+
up: [KEYCODE.UP, KEYCODE.LEFT],
|
|
55
|
+
down: [KEYCODE.DOWN, KEYCODE.RIGHT],
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const defaultProps = {
|
|
59
|
+
axis: "y",
|
|
60
|
+
disableAutoscroll: false,
|
|
61
|
+
distance: 0,
|
|
62
|
+
getHelperDimensions: defaultGetHelperDimensions,
|
|
63
|
+
hideSortableGhost: true,
|
|
64
|
+
lockOffset: "50%",
|
|
65
|
+
lockToContainerEdges: false,
|
|
66
|
+
pressDelay: 0,
|
|
67
|
+
pressThreshold: 5,
|
|
68
|
+
keyCodes: defaultKeyCodes,
|
|
69
|
+
shouldCancelStart: defaultShouldCancelStart,
|
|
70
|
+
transitionDuration: 300,
|
|
71
|
+
useWindowAsScrollContainer: false,
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export const omittedProps = Object.keys(propTypes)
|
|
75
|
+
|
|
76
|
+
export function validateProps(props) {
|
|
77
|
+
invariant(
|
|
78
|
+
!(props.distance && props.pressDelay),
|
|
79
|
+
"Attempted to set both `pressDelay` and `distance` on SortableContainer, you may only use one or the other, not both at the same time.",
|
|
80
|
+
)
|
|
81
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/* @flow */
|
|
2
|
+
import * as React from "react"
|
|
3
|
+
import PropTypes from "prop-types"
|
|
4
|
+
import invariant from "invariant"
|
|
5
|
+
import {SortableContext} from "./SortableContainer"
|
|
6
|
+
|
|
7
|
+
import {provideDisplayName, omit} from "./utils"
|
|
8
|
+
|
|
9
|
+
const propTypes = {
|
|
10
|
+
index: PropTypes.number.isRequired,
|
|
11
|
+
collection: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
12
|
+
disabled: PropTypes.bool,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const omittedProps = Object.keys(propTypes)
|
|
16
|
+
|
|
17
|
+
export default function sortableElement(WrappedComponent, config = {withRef: false}) {
|
|
18
|
+
return class WithSortableElement extends React.Component {
|
|
19
|
+
static displayName = provideDisplayName("sortableElement", WrappedComponent)
|
|
20
|
+
|
|
21
|
+
static contextType = SortableContext
|
|
22
|
+
|
|
23
|
+
static propTypes = propTypes
|
|
24
|
+
|
|
25
|
+
static defaultProps = {
|
|
26
|
+
collection: 0,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
nodeRef = React.createRef()
|
|
30
|
+
wrappedInstance = React.createRef()
|
|
31
|
+
|
|
32
|
+
componentDidMount() {
|
|
33
|
+
this.register()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
componentDidUpdate(prevProps) {
|
|
37
|
+
const node = this.nodeRef.current
|
|
38
|
+
|
|
39
|
+
if (node) {
|
|
40
|
+
if (prevProps.index !== this.props.index) {
|
|
41
|
+
node.sortableInfo.index = this.props.index
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (prevProps.disabled !== this.props.disabled) {
|
|
45
|
+
node.sortableInfo.disabled = this.props.disabled
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (prevProps.collection !== this.props.collection) {
|
|
50
|
+
this.unregister(prevProps.collection)
|
|
51
|
+
this.register()
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
componentWillUnmount() {
|
|
56
|
+
this.unregister()
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
register() {
|
|
60
|
+
const {collection, disabled, index} = this.props
|
|
61
|
+
const node = this.nodeRef.current
|
|
62
|
+
|
|
63
|
+
if (node) {
|
|
64
|
+
node.sortableInfo = {
|
|
65
|
+
collection,
|
|
66
|
+
disabled,
|
|
67
|
+
index,
|
|
68
|
+
manager: this.context.manager,
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
this.node = node
|
|
73
|
+
this.ref = {node}
|
|
74
|
+
|
|
75
|
+
this.context.manager.add(collection, this.ref)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
unregister(collection = this.props.collection) {
|
|
79
|
+
this.context.manager.remove(collection, this.ref)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
getWrappedInstance() {
|
|
83
|
+
invariant(
|
|
84
|
+
config.withRef,
|
|
85
|
+
"To access the wrapped instance, you need to pass in {withRef: true} as the second argument of the SortableElement() call",
|
|
86
|
+
)
|
|
87
|
+
return this.wrappedInstance.current
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
render() {
|
|
91
|
+
const ref = config.withRef ? this.wrappedInstance : null
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<WrappedComponent
|
|
95
|
+
ref={node => {
|
|
96
|
+
if (node) {
|
|
97
|
+
this.nodeRef.current = node
|
|
98
|
+
node.sortableInfo = {
|
|
99
|
+
collection: this.props.collection,
|
|
100
|
+
disabled: this.props.disabled,
|
|
101
|
+
index: this.props.index,
|
|
102
|
+
manager: this.context.manager,
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (ref) ref.current = node
|
|
106
|
+
}}
|
|
107
|
+
{...omit(this.props, omittedProps)} index={this.props.index} />
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/* @flow */
|
|
2
|
+
import * as React from "react"
|
|
3
|
+
import invariant from "invariant"
|
|
4
|
+
|
|
5
|
+
import {provideDisplayName} from "./utils"
|
|
6
|
+
|
|
7
|
+
export default function sortableHandle(WrappedComponent, config = {withRef: false}) {
|
|
8
|
+
return class WithSortableHandle extends React.Component {
|
|
9
|
+
static displayName = provideDisplayName("sortableHandle", WrappedComponent)
|
|
10
|
+
|
|
11
|
+
wrappedInstance = React.createRef()
|
|
12
|
+
nodeRef = React.createRef()
|
|
13
|
+
|
|
14
|
+
componentDidMount() {
|
|
15
|
+
const node = this.nodeRef.current
|
|
16
|
+
if (node) {
|
|
17
|
+
node.sortableHandle = true
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
getWrappedInstance() {
|
|
22
|
+
invariant(
|
|
23
|
+
config.withRef,
|
|
24
|
+
"To access the wrapped instance, you need to pass in {withRef: true} as the second argument of the SortableHandle() call",
|
|
25
|
+
)
|
|
26
|
+
return this.wrappedInstance.current
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
render() {
|
|
30
|
+
const ref = config.withRef ? this.wrappedInstance : null
|
|
31
|
+
|
|
32
|
+
return <WrappedComponent ref={node => {
|
|
33
|
+
if (node) {
|
|
34
|
+
this.nodeRef.current = node
|
|
35
|
+
node.sortableHandle = true
|
|
36
|
+
}
|
|
37
|
+
if (ref) ref.current = node
|
|
38
|
+
}} {...this.props} />
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function isSortableHandle(node) {
|
|
44
|
+
return node.sortableHandle != null
|
|
45
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/* @flow */
|
|
2
|
+
export {default as SortableContainer} from "./SortableContainer"
|
|
3
|
+
export {default as SortableElement} from "./SortableElement"
|
|
4
|
+
export {default as SortableHandle} from "./SortableHandle"
|
|
5
|
+
export {default as DragHandle} from "./DragHandle"
|
|
6
|
+
|
|
7
|
+
export {default as sortableContainer} from "./SortableContainer"
|
|
8
|
+
export {default as sortableElement} from "./SortableElement"
|
|
9
|
+
export {default as sortableHandle} from "./SortableHandle"
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/* @flow */
|
|
2
|
+
import invariant from "invariant"
|
|
3
|
+
|
|
4
|
+
export function omit(obj, keysToOmit) {
|
|
5
|
+
return Object.keys(obj).reduce((acc, key) => {
|
|
6
|
+
if (keysToOmit.indexOf(key) === -1) {
|
|
7
|
+
acc[key] = obj[key]
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
return acc
|
|
11
|
+
}, {})
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const events = {
|
|
15
|
+
end: ["touchend", "touchcancel", "mouseup"],
|
|
16
|
+
move: ["touchmove", "mousemove"],
|
|
17
|
+
start: ["touchstart", "mousedown"],
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const vendorPrefix = (function () {
|
|
21
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
22
|
+
// Server environment
|
|
23
|
+
return ""
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// fix for: https://bugzilla.mozilla.org/show_bug.cgi?id=548397
|
|
27
|
+
// window.getComputedStyle() returns null inside an iframe with display: none
|
|
28
|
+
// in this case return an array with a fake mozilla style in it.
|
|
29
|
+
const styles = window.getComputedStyle(document.documentElement, "") || ["-moz-hidden-iframe"]
|
|
30
|
+
const pre = (Array.prototype.slice
|
|
31
|
+
.call(styles)
|
|
32
|
+
.join("")
|
|
33
|
+
.match(/-(moz|webkit|ms)-/) ||
|
|
34
|
+
(styles.OLink === "" && ["", "o"]))[1]
|
|
35
|
+
|
|
36
|
+
switch (pre) {
|
|
37
|
+
case "ms":
|
|
38
|
+
return "ms"
|
|
39
|
+
default:
|
|
40
|
+
return pre && pre.length ? pre[0].toUpperCase() + pre.substr(1) : ""
|
|
41
|
+
}
|
|
42
|
+
})()
|
|
43
|
+
|
|
44
|
+
export function setInlineStyles(node, styles) {
|
|
45
|
+
Object.keys(styles).forEach((key) => {
|
|
46
|
+
node.style[key] = styles[key]
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function setTranslate3d(node, translate) {
|
|
51
|
+
node.style[`${vendorPrefix}Transform`] =
|
|
52
|
+
translate == null ? "" : `translate3d(${translate.x}px,${translate.y}px,0)`
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function setTransitionDuration(node, duration) {
|
|
56
|
+
node.style[`${vendorPrefix}TransitionDuration`] = duration == null ? "" : `${duration}ms`
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function closest(el, fn) {
|
|
60
|
+
while (el) {
|
|
61
|
+
if (fn(el)) {
|
|
62
|
+
return el
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
el = el.parentNode
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return null
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function limit(min, max, value) {
|
|
72
|
+
return Math.max(min, Math.min(value, max))
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function getPixelValue(stringValue) {
|
|
76
|
+
if (stringValue.substr(-2) === "px") {
|
|
77
|
+
return parseFloat(stringValue)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return 0
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function getElementMargin(element) {
|
|
84
|
+
const style = window.getComputedStyle(element)
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
bottom: getPixelValue(style.marginBottom),
|
|
88
|
+
left: getPixelValue(style.marginLeft),
|
|
89
|
+
right: getPixelValue(style.marginRight),
|
|
90
|
+
top: getPixelValue(style.marginTop),
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function provideDisplayName(prefix, Component) {
|
|
95
|
+
const componentName = Component.displayName || Component.name
|
|
96
|
+
|
|
97
|
+
return componentName ? `${prefix}(${componentName})` : prefix
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function getScrollAdjustedBoundingClientRect(node, scrollDelta) {
|
|
101
|
+
const boundingClientRect = node.getBoundingClientRect()
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
top: boundingClientRect.top + scrollDelta.top,
|
|
105
|
+
left: boundingClientRect.left + scrollDelta.left,
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function getPosition(event) {
|
|
110
|
+
if (event.touches && event.touches.length) {
|
|
111
|
+
return {
|
|
112
|
+
x: event.touches[0].pageX,
|
|
113
|
+
y: event.touches[0].pageY,
|
|
114
|
+
}
|
|
115
|
+
} else if (event.changedTouches && event.changedTouches.length) {
|
|
116
|
+
return {
|
|
117
|
+
x: event.changedTouches[0].pageX,
|
|
118
|
+
y: event.changedTouches[0].pageY,
|
|
119
|
+
}
|
|
120
|
+
} else {
|
|
121
|
+
return {
|
|
122
|
+
x: event.pageX,
|
|
123
|
+
y: event.pageY,
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function isTouchEvent(event) {
|
|
129
|
+
return (
|
|
130
|
+
(event.touches && event.touches.length) || (event.changedTouches && event.changedTouches.length)
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export function getEdgeOffset(node, parent, offset = {left: 0, top: 0}) {
|
|
135
|
+
if (!node) {
|
|
136
|
+
return undefined
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Get the actual offsetTop / offsetLeft value, no matter how deep the node is nested
|
|
140
|
+
const nodeOffset = {
|
|
141
|
+
left: offset.left + node.offsetLeft,
|
|
142
|
+
top: offset.top + node.offsetTop,
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (node.parentNode === parent) {
|
|
146
|
+
return nodeOffset
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return getEdgeOffset(node.parentNode, parent, nodeOffset)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function getTargetIndex(newIndex, prevIndex, oldIndex) {
|
|
153
|
+
if (newIndex < oldIndex && newIndex > prevIndex) {
|
|
154
|
+
return newIndex - 1
|
|
155
|
+
} else if (newIndex > oldIndex && newIndex < prevIndex) {
|
|
156
|
+
return newIndex + 1
|
|
157
|
+
} else {
|
|
158
|
+
return newIndex
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function getLockPixelOffset({lockOffset, width, height}) {
|
|
163
|
+
let offsetX = lockOffset
|
|
164
|
+
let offsetY = lockOffset
|
|
165
|
+
let unit = "px"
|
|
166
|
+
|
|
167
|
+
if (typeof lockOffset === "string") {
|
|
168
|
+
const match = /^[+-]?\d*(?:\.\d*)?(px|%)$/.exec(lockOffset)
|
|
169
|
+
|
|
170
|
+
invariant(
|
|
171
|
+
match !== null,
|
|
172
|
+
"lockOffset value should be a number or a string of a " +
|
|
173
|
+
'number followed by "px" or "%". Given %s',
|
|
174
|
+
lockOffset,
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
offsetX = parseFloat(lockOffset)
|
|
178
|
+
offsetY = parseFloat(lockOffset)
|
|
179
|
+
unit = match[1]
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
invariant(
|
|
183
|
+
isFinite(offsetX) && isFinite(offsetY),
|
|
184
|
+
"lockOffset value should be a finite. Given %s",
|
|
185
|
+
lockOffset,
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
if (unit === "%") {
|
|
189
|
+
offsetX = (offsetX * width) / 100
|
|
190
|
+
offsetY = (offsetY * height) / 100
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return {
|
|
194
|
+
x: offsetX,
|
|
195
|
+
y: offsetY,
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export function getLockPixelOffsets({height, width, lockOffset}) {
|
|
200
|
+
const offsets = Array.isArray(lockOffset) ? lockOffset : [lockOffset, lockOffset]
|
|
201
|
+
|
|
202
|
+
invariant(
|
|
203
|
+
offsets.length === 2,
|
|
204
|
+
"lockOffset prop of SortableContainer should be a single " +
|
|
205
|
+
"value or an array of exactly two values. Given %s",
|
|
206
|
+
lockOffset,
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
const [minLockOffset, maxLockOffset] = offsets
|
|
210
|
+
|
|
211
|
+
return [
|
|
212
|
+
getLockPixelOffset({height, lockOffset: minLockOffset, width}),
|
|
213
|
+
getLockPixelOffset({height, lockOffset: maxLockOffset, width}),
|
|
214
|
+
]
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function isScrollable(el) {
|
|
218
|
+
const computedStyle = window.getComputedStyle(el)
|
|
219
|
+
const overflowRegex = /(auto|scroll)/
|
|
220
|
+
const properties = ["overflow", "overflowX", "overflowY"]
|
|
221
|
+
|
|
222
|
+
return properties.find((property) => overflowRegex.test(computedStyle[property]))
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export function getScrollingParent(el) {
|
|
226
|
+
if (!(el instanceof HTMLElement)) {
|
|
227
|
+
return null
|
|
228
|
+
} else if (isScrollable(el)) {
|
|
229
|
+
return el
|
|
230
|
+
} else {
|
|
231
|
+
return getScrollingParent(el.parentNode)
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export function getContainerGridGap(element) {
|
|
236
|
+
const style = window.getComputedStyle(element)
|
|
237
|
+
|
|
238
|
+
if (style.display === "grid") {
|
|
239
|
+
return {
|
|
240
|
+
x: getPixelValue(style.gridColumnGap),
|
|
241
|
+
y: getPixelValue(style.gridRowGap),
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return {x: 0, y: 0}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export const KEYCODE = {
|
|
249
|
+
TAB: 9,
|
|
250
|
+
ESC: 27,
|
|
251
|
+
SPACE: 32,
|
|
252
|
+
LEFT: 37,
|
|
253
|
+
UP: 38,
|
|
254
|
+
RIGHT: 39,
|
|
255
|
+
DOWN: 40,
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export const NodeType = {
|
|
259
|
+
Anchor: "A",
|
|
260
|
+
Button: "BUTTON",
|
|
261
|
+
Canvas: "CANVAS",
|
|
262
|
+
Input: "INPUT",
|
|
263
|
+
Option: "OPTION",
|
|
264
|
+
Textarea: "TEXTAREA",
|
|
265
|
+
Select: "SELECT",
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export function cloneNode(node) {
|
|
269
|
+
const selector = "input, textarea, select, canvas, [contenteditable]"
|
|
270
|
+
const fields = node.querySelectorAll(selector)
|
|
271
|
+
const clonedNode = node.cloneNode(true)
|
|
272
|
+
const clonedFields = [...clonedNode.querySelectorAll(selector)]
|
|
273
|
+
|
|
274
|
+
clonedFields.forEach((field, i) => {
|
|
275
|
+
if (field.type !== "file") {
|
|
276
|
+
field.value = fields[i].value
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Fixes an issue with original radio buttons losing their value once the
|
|
280
|
+
// clone is inserted in the DOM, as radio button `name` attributes must be unique
|
|
281
|
+
if (field.type === "radio" && field.name) {
|
|
282
|
+
field.name = `__sortableClone__${field.name}`
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (field.tagName === NodeType.Canvas && fields[i].width > 0 && fields[i].height > 0) {
|
|
286
|
+
const destCtx = field.getContext("2d")
|
|
287
|
+
destCtx.drawImage(fields[i], 0, 0)
|
|
288
|
+
}
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
return clonedNode
|
|
292
|
+
}
|