@gm-pc/sortable 1.24.9-beta.11 → 1.24.9-beta.13

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gm-pc/sortable",
3
- "version": "1.24.9-beta.11",
3
+ "version": "1.24.9-beta.13",
4
4
  "description": "观麦科技拖拽组件",
5
5
  "author": "liyatang <liyatang@qq.com>",
6
6
  "homepage": "https://github.com/gmfe/gm-pc#readme",
@@ -27,11 +27,11 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "@gm-common/tool": "^2.10.0",
30
- "@gm-pc/react": "^1.24.9-beta.11",
30
+ "@gm-pc/react": "^1.24.9-beta.13",
31
31
  "lodash": "^4.17.19",
32
32
  "sortablejs": "^1.12.0"
33
33
  },
34
- "gitHead": "7c93cbae57353cc67b9bdce650e22312882a1b4a",
34
+ "gitHead": "b773c85a7a6d591837f7f90058bbbc3c596f5a8c",
35
35
  "devDependencies": {
36
36
  "@types/sortablejs": "^1.13.0"
37
37
  }
@@ -1,69 +1,69 @@
1
- import React, { useMemo } from 'react'
2
- import classNames from 'classnames'
3
- import { devWarnForHook } from '@gm-common/tool'
4
- import { Value, SortableDataItem, SortableProps } from './types'
5
- import SortableBase from './sortable_base'
6
- import { Options } from 'sortablejs'
7
-
8
- const Sortable = ({
9
- data,
10
- onChange,
11
- groupValues,
12
- renderItem = (item: SortableDataItem) => item.text,
13
- itemProps = {},
14
- tag,
15
- options = {},
16
- ...rest
17
- }: SortableProps) => {
18
- devWarnForHook(() => {
19
- if (groupValues && !options.group) {
20
- console.warn('groupValues need options.group')
21
- }
22
- })
23
-
24
- let filterData = data
25
- if (groupValues) {
26
- filterData = data.filter((value) => groupValues.includes(value.value))
27
- }
28
-
29
- const handleChange = (values: string[]) => {
30
- // 因为 SortableJS 默认吐出来都是 string,所以需要反编译拿回原来的类型
31
- const newValues: Value[] = values.map((value) => JSON.parse(value))
32
- const newValuesMap = new Map<string, SortableDataItem>()
33
- data.forEach((value) => {
34
- newValuesMap.set(value.value, value)
35
- })
36
- const newData: SortableDataItem[] = newValues.map((value) => newValuesMap.get(value)!)
37
- onChange(newData)
38
- }
39
-
40
- const items = useMemo(
41
- () =>
42
- filterData.map((value, index) => (
43
- <div
44
- key={value.value as any}
45
- data-id={JSON.stringify(value.value)}
46
- {...itemProps}
47
- className={classNames(
48
- { 'gm-cursor-grab': !options.handle },
49
- itemProps.className
50
- )}
51
- >
52
- {renderItem(value, index)}
53
- </div>
54
- )),
55
- [filterData, renderItem, itemProps, options.handle]
56
- )
57
-
58
- return (
59
- <SortableBase
60
- {...rest}
61
- tag={tag}
62
- options={{ animation: 150, ...options }}
63
- onChange={handleChange}
64
- >
65
- {items}
66
- </SortableBase>
67
- )
68
- }
69
- export default Sortable
1
+ import React, { useMemo } from 'react'
2
+ import classNames from 'classnames'
3
+ import { devWarnForHook } from '@gm-common/tool'
4
+ import { Value, SortableDataItem, SortableProps } from './types'
5
+ import SortableBase from './sortable_base'
6
+ import { Options } from 'sortablejs'
7
+
8
+ const Sortable = ({
9
+ data,
10
+ onChange,
11
+ groupValues,
12
+ renderItem = (item: SortableDataItem) => item.text,
13
+ itemProps = {},
14
+ tag,
15
+ options = {},
16
+ ...rest
17
+ }: SortableProps) => {
18
+ devWarnForHook(() => {
19
+ if (groupValues && !options.group) {
20
+ console.warn('groupValues need options.group')
21
+ }
22
+ })
23
+
24
+ let filterData = data
25
+ if (groupValues) {
26
+ filterData = data.filter((value) => groupValues.includes(value.value))
27
+ }
28
+
29
+ const handleChange = (values: string[]) => {
30
+ // 因为 SortableJS 默认吐出来都是 string,所以需要反编译拿回原来的类型
31
+ const newValues: Value[] = values.map((value) => JSON.parse(value))
32
+ const newValuesMap = new Map<string, SortableDataItem>()
33
+ data.forEach((value) => {
34
+ newValuesMap.set(value.value, value)
35
+ })
36
+ const newData: SortableDataItem[] = newValues.map((value) => newValuesMap.get(value)!)
37
+ onChange(newData)
38
+ }
39
+
40
+ const items = useMemo(
41
+ () =>
42
+ filterData.map((value, index) => (
43
+ <div
44
+ key={value.value as any}
45
+ data-id={JSON.stringify(value.value)}
46
+ {...itemProps}
47
+ className={classNames(
48
+ { 'gm-cursor-grab': !options.handle },
49
+ itemProps.className
50
+ )}
51
+ >
52
+ {renderItem(value, index)}
53
+ </div>
54
+ )),
55
+ [filterData, renderItem, itemProps, options.handle]
56
+ )
57
+
58
+ return (
59
+ <SortableBase
60
+ {...rest}
61
+ tag={tag}
62
+ options={{ animation: 150, ...options }}
63
+ onChange={handleChange}
64
+ >
65
+ {items}
66
+ </SortableBase>
67
+ )
68
+ }
69
+ export default Sortable
@@ -1,127 +1,127 @@
1
- import React, { Component } from 'react'
2
- import Sortable, { Options, SortableEvent, MoveEvent } from 'sortablejs'
3
- import { SortableBaseProps } from './types'
4
-
5
- type SortableEventType = Extract<
6
- keyof Options,
7
- | 'onChoose'
8
- | 'onStart'
9
- | 'onEnd'
10
- | 'onAdd'
11
- | 'onUpdate'
12
- | 'onSort'
13
- | 'onRemove'
14
- | 'onFilter'
15
- | 'onMove'
16
- | 'onClone'
17
- >
18
-
19
- const SORTABLE_EVENTS: SortableEventType[] = [
20
- 'onChoose',
21
- 'onStart',
22
- 'onEnd',
23
- 'onAdd',
24
- 'onUpdate',
25
- 'onSort',
26
- 'onRemove',
27
- 'onFilter',
28
- 'onMove',
29
- 'onClone',
30
- ]
31
-
32
- interface Store {
33
- nextSibling: Element | null
34
- activeComponent: SortableBase | null
35
- }
36
-
37
- const store: Store = { nextSibling: null, activeComponent: null }
38
-
39
- class SortableBase extends Component<SortableBaseProps> {
40
- static defaultProps = {
41
- options: {},
42
- tag: 'div',
43
- style: {},
44
- }
45
-
46
- private _node: HTMLElement | undefined
47
- private _sortable: Sortable | undefined
48
-
49
- componentDidMount() {
50
- const option: Options = { ...this.props.options, disabled: this.props.disabled }
51
- SORTABLE_EVENTS.forEach((name) => {
52
- const eventHandler = option[name] as (
53
- event: SortableEvent | MoveEvent,
54
- originalEvent?: Event
55
- ) => void | boolean | -1 | 1
56
- ;(option[name] as (
57
- event: SortableEvent | MoveEvent,
58
- originalEvent?: Event
59
- ) => void | boolean | -1 | 1) = (event, originalEvent) => {
60
- const _evt = event as SortableEvent
61
- if (name === 'onChoose') {
62
- store.nextSibling = _evt.item.nextElementSibling
63
- store.activeComponent = this
64
- } else if ((name === 'onAdd' || name === 'onUpdate') && this.props.onChange) {
65
- const items = this._sortable?.toArray()
66
- const remote = store.activeComponent
67
- const remoteItems = remote?._sortable?.toArray()
68
- const referenceNode =
69
- store.nextSibling && store.nextSibling.parentNode !== null
70
- ? store.nextSibling
71
- : null
72
- _evt.from.insertBefore(_evt.item, referenceNode)
73
- if (remote !== this) {
74
- const remoteOptions = remote?.props.options ?? {}
75
- if (
76
- typeof remoteOptions.group === 'object' &&
77
- remoteOptions.group.pull === 'clone'
78
- ) {
79
- // remove the node with the same data-id
80
- // eslint-disable-next-line
81
- _evt.item.parentNode?.removeChild(_evt.item)
82
- }
83
- remote?.props.onChange &&
84
- remote.props.onChange(remoteItems!, remote._sortable!, _evt)
85
- }
86
- this.props.onChange && this.props.onChange(items!, this._sortable!, _evt)
87
- }
88
-
89
- if ((event as MoveEvent).type === 'move') {
90
- return eventHandler ? eventHandler(event, originalEvent) : true
91
- }
92
- setTimeout(() => {
93
- eventHandler && eventHandler(event)
94
- }, 0)
95
- }
96
- })
97
- this._sortable = Sortable.create(this._node!, option) // 不可直接解构使用 create,原因未知
98
- }
99
-
100
- // eslint-disable-next-line camelcase
101
- UNSAFE_componentWillReceiveProps(nextProps: Readonly<SortableBaseProps>) {
102
- if (nextProps.disabled !== this.props.disabled) {
103
- // eslint-disable-next-line
104
- this._sortable?.option('disabled', nextProps.disabled)
105
- }
106
- }
107
-
108
- shouldComponentUpdate(nextProps: Readonly<SortableBaseProps>): boolean {
109
- // If onChange is null, it is an UnControlled component
110
- // Don't let React re-render it by setting return to false
111
- return !!nextProps.onChange
112
- }
113
-
114
- componentWillUnmount() {
115
- if (this._sortable) {
116
- this._sortable.destroy()
117
- this._sortable = undefined
118
- }
119
- }
120
-
121
- render() {
122
- const { tag: Tag, options, onChange, disabled, ...rest } = this.props
123
- return <Tag {...rest} ref={(ref: HTMLElement) => (this._node = ref)} />
124
- }
125
- }
126
-
127
- export default SortableBase
1
+ import React, { Component } from 'react'
2
+ import Sortable, { Options, SortableEvent, MoveEvent } from 'sortablejs'
3
+ import { SortableBaseProps } from './types'
4
+
5
+ type SortableEventType = Extract<
6
+ keyof Options,
7
+ | 'onChoose'
8
+ | 'onStart'
9
+ | 'onEnd'
10
+ | 'onAdd'
11
+ | 'onUpdate'
12
+ | 'onSort'
13
+ | 'onRemove'
14
+ | 'onFilter'
15
+ | 'onMove'
16
+ | 'onClone'
17
+ >
18
+
19
+ const SORTABLE_EVENTS: SortableEventType[] = [
20
+ 'onChoose',
21
+ 'onStart',
22
+ 'onEnd',
23
+ 'onAdd',
24
+ 'onUpdate',
25
+ 'onSort',
26
+ 'onRemove',
27
+ 'onFilter',
28
+ 'onMove',
29
+ 'onClone',
30
+ ]
31
+
32
+ interface Store {
33
+ nextSibling: Element | null
34
+ activeComponent: SortableBase | null
35
+ }
36
+
37
+ const store: Store = { nextSibling: null, activeComponent: null }
38
+
39
+ class SortableBase extends Component<SortableBaseProps> {
40
+ static defaultProps = {
41
+ options: {},
42
+ tag: 'div',
43
+ style: {},
44
+ }
45
+
46
+ private _node: HTMLElement | undefined
47
+ private _sortable: Sortable | undefined
48
+
49
+ componentDidMount() {
50
+ const option: Options = { ...this.props.options, disabled: this.props.disabled }
51
+ SORTABLE_EVENTS.forEach((name) => {
52
+ const eventHandler = option[name] as (
53
+ event: SortableEvent | MoveEvent,
54
+ originalEvent?: Event
55
+ ) => void | boolean | -1 | 1
56
+ ;(option[name] as (
57
+ event: SortableEvent | MoveEvent,
58
+ originalEvent?: Event
59
+ ) => void | boolean | -1 | 1) = (event, originalEvent) => {
60
+ const _evt = event as SortableEvent
61
+ if (name === 'onChoose') {
62
+ store.nextSibling = _evt.item.nextElementSibling
63
+ store.activeComponent = this
64
+ } else if ((name === 'onAdd' || name === 'onUpdate') && this.props.onChange) {
65
+ const items = this._sortable?.toArray()
66
+ const remote = store.activeComponent
67
+ const remoteItems = remote?._sortable?.toArray()
68
+ const referenceNode =
69
+ store.nextSibling && store.nextSibling.parentNode !== null
70
+ ? store.nextSibling
71
+ : null
72
+ _evt.from.insertBefore(_evt.item, referenceNode)
73
+ if (remote !== this) {
74
+ const remoteOptions = remote?.props.options ?? {}
75
+ if (
76
+ typeof remoteOptions.group === 'object' &&
77
+ remoteOptions.group.pull === 'clone'
78
+ ) {
79
+ // remove the node with the same data-id
80
+ // eslint-disable-next-line
81
+ _evt.item.parentNode?.removeChild(_evt.item)
82
+ }
83
+ remote?.props.onChange &&
84
+ remote.props.onChange(remoteItems!, remote._sortable!, _evt)
85
+ }
86
+ this.props.onChange && this.props.onChange(items!, this._sortable!, _evt)
87
+ }
88
+
89
+ if ((event as MoveEvent).type === 'move') {
90
+ return eventHandler ? eventHandler(event, originalEvent) : true
91
+ }
92
+ setTimeout(() => {
93
+ eventHandler && eventHandler(event)
94
+ }, 0)
95
+ }
96
+ })
97
+ this._sortable = Sortable.create(this._node!, option) // 不可直接解构使用 create,原因未知
98
+ }
99
+
100
+ // eslint-disable-next-line camelcase
101
+ UNSAFE_componentWillReceiveProps(nextProps: Readonly<SortableBaseProps>) {
102
+ if (nextProps.disabled !== this.props.disabled) {
103
+ // eslint-disable-next-line
104
+ this._sortable?.option('disabled', nextProps.disabled)
105
+ }
106
+ }
107
+
108
+ shouldComponentUpdate(nextProps: Readonly<SortableBaseProps>): boolean {
109
+ // If onChange is null, it is an UnControlled component
110
+ // Don't let React re-render it by setting return to false
111
+ return !!nextProps.onChange
112
+ }
113
+
114
+ componentWillUnmount() {
115
+ if (this._sortable) {
116
+ this._sortable.destroy()
117
+ this._sortable = undefined
118
+ }
119
+ }
120
+
121
+ render() {
122
+ const { tag: Tag, options, onChange, disabled, ...rest } = this.props
123
+ return <Tag {...rest} ref={(ref: HTMLElement) => (this._node = ref)} />
124
+ }
125
+ }
126
+
127
+ export default SortableBase
@@ -1,63 +1,63 @@
1
- import React, { useMemo, useRef } from 'react'
2
- import _ from 'lodash'
3
- import { GroupSortableProps, SortableDataItem } from './types'
4
- import Sortable from './sortable'
5
-
6
- const GroupSortable = ({
7
- data,
8
- onChange,
9
- renderItem,
10
- itemProps,
11
- tag,
12
- options,
13
- children,
14
- }: GroupSortableProps) => {
15
- /**
16
- * 两个列表之间的拖动,中间变量
17
- */
18
- const dataRef = useRef<SortableDataItem[][]>([])
19
- const flatData = useMemo(() => _.flatten(data), [data])
20
- const items = data.map((subData, index) => {
21
- const handleChange = (newSubData: SortableDataItem[]): void => {
22
- // 变化的才会触发 change,
23
- // 单个列表内拖动只一次 change,此时 newSubData 长度和原先一样
24
- // 如果列表之间拖动,当且仅当两次 change,此时 newSubData 长度和原先不一样
25
- if (newSubData.length === data[index].length) {
26
- const newData = data.slice()
27
- newData[index] = newSubData
28
- onChange(newData)
29
- } else {
30
- // 初次进入,会先修改被拖出的数组
31
- if (dataRef.current.length === 0) {
32
- // 第一次会先将 dataRef 填充,并将被拖出的那一项修改为 newSubData
33
- dataRef.current = data.slice()
34
- dataRef.current[index] = newSubData
35
- } else {
36
- // 第二次会拿到 dataRef,并将被拖入的那一项修改为 newSubData
37
- dataRef.current[index] = newSubData
38
- // 避免引用 slice
39
- const newData = dataRef.current.slice()
40
- // 还原
41
- dataRef.current = []
42
- onChange(newData)
43
- }
44
- }
45
- }
46
-
47
- return (
48
- <Sortable
49
- key={_.uniqueId()}
50
- data={flatData}
51
- groupValues={subData.map((val) => val.value)}
52
- onChange={handleChange}
53
- renderItem={renderItem}
54
- itemProps={itemProps}
55
- tag={tag}
56
- options={{ group: 'group', ...options }}
57
- />
58
- )
59
- })
60
- return children(items)
61
- }
62
-
63
- export default GroupSortable
1
+ import React, { useMemo, useRef } from 'react'
2
+ import _ from 'lodash'
3
+ import { GroupSortableProps, SortableDataItem } from './types'
4
+ import Sortable from './sortable'
5
+
6
+ const GroupSortable = ({
7
+ data,
8
+ onChange,
9
+ renderItem,
10
+ itemProps,
11
+ tag,
12
+ options,
13
+ children,
14
+ }: GroupSortableProps) => {
15
+ /**
16
+ * 两个列表之间的拖动,中间变量
17
+ */
18
+ const dataRef = useRef<SortableDataItem[][]>([])
19
+ const flatData = useMemo(() => _.flatten(data), [data])
20
+ const items = data.map((subData, index) => {
21
+ const handleChange = (newSubData: SortableDataItem[]): void => {
22
+ // 变化的才会触发 change,
23
+ // 单个列表内拖动只一次 change,此时 newSubData 长度和原先一样
24
+ // 如果列表之间拖动,当且仅当两次 change,此时 newSubData 长度和原先不一样
25
+ if (newSubData.length === data[index].length) {
26
+ const newData = data.slice()
27
+ newData[index] = newSubData
28
+ onChange(newData)
29
+ } else {
30
+ // 初次进入,会先修改被拖出的数组
31
+ if (dataRef.current.length === 0) {
32
+ // 第一次会先将 dataRef 填充,并将被拖出的那一项修改为 newSubData
33
+ dataRef.current = data.slice()
34
+ dataRef.current[index] = newSubData
35
+ } else {
36
+ // 第二次会拿到 dataRef,并将被拖入的那一项修改为 newSubData
37
+ dataRef.current[index] = newSubData
38
+ // 避免引用 slice
39
+ const newData = dataRef.current.slice()
40
+ // 还原
41
+ dataRef.current = []
42
+ onChange(newData)
43
+ }
44
+ }
45
+ }
46
+
47
+ return (
48
+ <Sortable
49
+ key={_.uniqueId()}
50
+ data={flatData}
51
+ groupValues={subData.map((val) => val.value)}
52
+ onChange={handleChange}
53
+ renderItem={renderItem}
54
+ itemProps={itemProps}
55
+ tag={tag}
56
+ options={{ group: 'group', ...options }}
57
+ />
58
+ )
59
+ })
60
+ return children(items)
61
+ }
62
+
63
+ export default GroupSortable
@@ -1,50 +1,50 @@
1
- import Sortable, { Options, SortableEvent } from 'sortablejs'
2
- import { ElementType, HTMLAttributes, ReactElement, ReactNode } from 'react'
3
-
4
- type Value = any
5
-
6
- interface SortableBaseProps extends Omit<HTMLAttributes<HTMLElement>, 'onChange'> {
7
- options: Options
8
- onChange?(remoteItems: string[], sortable: Sortable, event: SortableEvent): void
9
- tag: ElementType
10
- disabled?: boolean
11
- }
12
-
13
- interface SortableDataItem {
14
- value: Value
15
- text: string
16
- [key: string]: any
17
- }
18
-
19
- interface SortableCommonProps extends Omit<HTMLAttributes<HTMLElement>, 'onChange'> {
20
- /**
21
- * options.group 有值的时候要传。
22
- * 此时 data 是 group 集合数据,groupValues 是当前组件的数据
23
- */
24
- groupValues?: Value[]
25
- renderItem?(value: SortableDataItem, index: number): ReactNode
26
- itemProps?: HTMLAttributes<HTMLDivElement>
27
- tag?: ElementType
28
- options?: Options
29
- disabled?: boolean
30
- }
31
-
32
- interface SortableProps extends SortableCommonProps {
33
- data: SortableDataItem[]
34
- onChange(data: SortableDataItem[]): void
35
- }
36
-
37
- interface GroupSortableProps extends SortableCommonProps {
38
- /* 二维数组 */
39
- data: SortableDataItem[][]
40
- onChange(data: SortableDataItem[][]): void
41
- children: (items: ReactElement<SortableProps>[]) => ReactElement
42
- }
43
-
44
- export type {
45
- Value,
46
- SortableBaseProps,
47
- SortableDataItem,
48
- SortableProps,
49
- GroupSortableProps,
50
- }
1
+ import Sortable, { Options, SortableEvent } from 'sortablejs'
2
+ import { ElementType, HTMLAttributes, ReactElement, ReactNode } from 'react'
3
+
4
+ type Value = any
5
+
6
+ interface SortableBaseProps extends Omit<HTMLAttributes<HTMLElement>, 'onChange'> {
7
+ options: Options
8
+ onChange?(remoteItems: string[], sortable: Sortable, event: SortableEvent): void
9
+ tag: ElementType
10
+ disabled?: boolean
11
+ }
12
+
13
+ interface SortableDataItem {
14
+ value: Value
15
+ text: string
16
+ [key: string]: any
17
+ }
18
+
19
+ interface SortableCommonProps extends Omit<HTMLAttributes<HTMLElement>, 'onChange'> {
20
+ /**
21
+ * options.group 有值的时候要传。
22
+ * 此时 data 是 group 集合数据,groupValues 是当前组件的数据
23
+ */
24
+ groupValues?: Value[]
25
+ renderItem?(value: SortableDataItem, index: number): ReactNode
26
+ itemProps?: HTMLAttributes<HTMLDivElement>
27
+ tag?: ElementType
28
+ options?: Options
29
+ disabled?: boolean
30
+ }
31
+
32
+ interface SortableProps extends SortableCommonProps {
33
+ data: SortableDataItem[]
34
+ onChange(data: SortableDataItem[]): void
35
+ }
36
+
37
+ interface GroupSortableProps extends SortableCommonProps {
38
+ /* 二维数组 */
39
+ data: SortableDataItem[][]
40
+ onChange(data: SortableDataItem[][]): void
41
+ children: (items: ReactElement<SortableProps>[]) => ReactElement
42
+ }
43
+
44
+ export type {
45
+ Value,
46
+ SortableBaseProps,
47
+ SortableDataItem,
48
+ SortableProps,
49
+ GroupSortableProps,
50
+ }
package/src/index.ts CHANGED
@@ -1,10 +1,10 @@
1
- export { default as Sortable } from './components/sortable'
2
- export { default as SortableBase } from './components/sortable_base'
3
- export { default as GroupSortable } from './components/sortable_group'
4
-
5
- export type {
6
- SortableProps,
7
- SortableBaseProps,
8
- SortableDataItem,
9
- GroupSortableProps,
10
- } from './components/types'
1
+ export { default as Sortable } from './components/sortable'
2
+ export { default as SortableBase } from './components/sortable_base'
3
+ export { default as GroupSortable } from './components/sortable_group'
4
+
5
+ export type {
6
+ SortableProps,
7
+ SortableBaseProps,
8
+ SortableDataItem,
9
+ GroupSortableProps,
10
+ } from './components/types'