@atlaskit/pragmatic-drag-and-drop 0.18.2 → 0.19.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/CHANGELOG.md +63 -0
- package/constellation/index/about.mdx +75 -12
- package/dist/cjs/entry-point/util/center-under-pointer.js +12 -0
- package/dist/cjs/entry-point/util/offset-from-pointer.js +12 -0
- package/dist/cjs/entry-point/util/set-custom-native-drag-preview.js +1 -1
- package/dist/cjs/util/custom-native-drag-preview/center-under-pointer.js +15 -0
- package/dist/cjs/util/custom-native-drag-preview/offset-from-pointer.js +25 -0
- package/dist/cjs/util/{set-custom-native-drag-preview.js → custom-native-drag-preview/set-custom-native-drag-preview.js} +15 -42
- package/dist/cjs/util/custom-native-drag-preview/types.js +5 -0
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/entry-point/util/center-under-pointer.js +1 -0
- package/dist/es2019/entry-point/util/offset-from-pointer.js +1 -0
- package/dist/es2019/entry-point/util/set-custom-native-drag-preview.js +1 -1
- package/dist/es2019/util/custom-native-drag-preview/center-under-pointer.js +9 -0
- package/dist/es2019/util/custom-native-drag-preview/offset-from-pointer.js +20 -0
- package/dist/es2019/util/{set-custom-native-drag-preview.js → custom-native-drag-preview/set-custom-native-drag-preview.js} +11 -40
- package/dist/es2019/util/custom-native-drag-preview/types.js +1 -0
- package/dist/es2019/version.json +1 -1
- package/dist/esm/entry-point/util/center-under-pointer.js +1 -0
- package/dist/esm/entry-point/util/offset-from-pointer.js +1 -0
- package/dist/esm/entry-point/util/set-custom-native-drag-preview.js +1 -1
- package/dist/esm/util/custom-native-drag-preview/center-under-pointer.js +8 -0
- package/dist/esm/util/custom-native-drag-preview/offset-from-pointer.js +19 -0
- package/dist/esm/util/{set-custom-native-drag-preview.js → custom-native-drag-preview/set-custom-native-drag-preview.js} +15 -42
- package/dist/esm/util/custom-native-drag-preview/types.js +1 -0
- package/dist/esm/version.json +1 -1
- package/dist/types/entry-point/util/center-under-pointer.d.ts +1 -0
- package/dist/types/entry-point/util/offset-from-pointer.d.ts +1 -0
- package/dist/types/entry-point/util/set-custom-native-drag-preview.d.ts +1 -1
- package/dist/types/util/custom-native-drag-preview/center-under-pointer.d.ts +2 -0
- package/dist/types/util/custom-native-drag-preview/offset-from-pointer.d.ts +10 -0
- package/dist/{types-ts4.5/util → types/util/custom-native-drag-preview}/set-custom-native-drag-preview.d.ts +4 -21
- package/dist/types/util/custom-native-drag-preview/types.d.ts +16 -0
- package/dist/types-ts4.5/entry-point/util/center-under-pointer.d.ts +1 -0
- package/dist/types-ts4.5/entry-point/util/offset-from-pointer.d.ts +1 -0
- package/dist/types-ts4.5/entry-point/util/set-custom-native-drag-preview.d.ts +1 -1
- package/dist/types-ts4.5/util/custom-native-drag-preview/center-under-pointer.d.ts +2 -0
- package/dist/types-ts4.5/util/custom-native-drag-preview/offset-from-pointer.d.ts +10 -0
- package/dist/{types/util → types-ts4.5/util/custom-native-drag-preview}/set-custom-native-drag-preview.d.ts +4 -21
- package/dist/types-ts4.5/util/custom-native-drag-preview/types.d.ts +16 -0
- package/package.json +4 -2
- package/util/center-under-pointer/package.json +15 -0
- package/util/offset-from-pointer/package.json +15 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,68 @@
|
|
|
1
1
|
# @atlaskit/pragmatic-drag-and-drop
|
|
2
2
|
|
|
3
|
+
## 0.19.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`8c301a251e4`](https://bitbucket.org/atlassian/atlassian-frontend/commits/8c301a251e4) - We have changed the API of `setCustomNativeDragPreview()` to allow increased control and slightly lower bundles as well.
|
|
8
|
+
|
|
9
|
+
We have removed the `placement` argument, and replaced it with `getOffset()`.
|
|
10
|
+
|
|
11
|
+
```diff
|
|
12
|
+
- placement: { type: 'center' } | { type: 'offset-from-pointer'; x: CSSValue; y: CSSValue };
|
|
13
|
+
+ getOffset: (args: { container: HTMLElement }) => {x: number, y: number}
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
`getOffset()` allows unlimited control over how to place the custom native drag preview relative to the users pointer. Please see our updated documentation for detailed information about the new `getOffset()` API. Our new `getOffset()` approach means that we also no longer need to bake in all `placement` options into the bundle - consumers now only pay for what they use!
|
|
17
|
+
|
|
18
|
+
`placement: { type: 'offset-from-pointer' }` has been replaced by `offsetFromPointer()`
|
|
19
|
+
|
|
20
|
+
```diff
|
|
21
|
+
import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/util/set-custom-native-drag-preview';
|
|
22
|
+
+ import { offsetFromPointer } from '@atlaskit/pragmatic-drag-and-drop/util/offset-from-pointer;
|
|
23
|
+
|
|
24
|
+
draggable({
|
|
25
|
+
element: myElement,
|
|
26
|
+
onGenerateDragPreview: ({ nativeSetDragImage }) => {
|
|
27
|
+
setCustomNativeDragPreview({
|
|
28
|
+
- placement: { type: 'offset-from-pointer', x: '16px', y: '8px' }
|
|
29
|
+
+ getOffset: offsetFromPointer({x: '16px', y: '8px'}),
|
|
30
|
+
render: function render({ container }) {
|
|
31
|
+
ReactDOM.render(<Preview item={item} />, container);
|
|
32
|
+
return function cleanup() {
|
|
33
|
+
ReactDOM.unmountComponentAtNode(container);
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
nativeSetDragImage,
|
|
37
|
+
});
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`placement: { type: 'center' }` has been replaced by `centerUnderPointer()`
|
|
43
|
+
|
|
44
|
+
```diff
|
|
45
|
+
import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/util/set-custom-native-drag-preview';
|
|
46
|
+
+ import { centerUnderPointer } from '@atlaskit/pragmatic-drag-and-drop/util/center-under-pointer-pointer;
|
|
47
|
+
|
|
48
|
+
draggable({
|
|
49
|
+
element: myElement,
|
|
50
|
+
onGenerateDragPreview: ({ nativeSetDragImage }) => {
|
|
51
|
+
setCustomNativeDragPreview({
|
|
52
|
+
- placement: { type: 'center' }
|
|
53
|
+
+ getOffset: centerUnderPointer,
|
|
54
|
+
render: function render({ container }) {
|
|
55
|
+
ReactDOM.render(<Preview item={item} />, container);
|
|
56
|
+
return function cleanup() {
|
|
57
|
+
ReactDOM.unmountComponentAtNode(container);
|
|
58
|
+
};
|
|
59
|
+
},
|
|
60
|
+
nativeSetDragImage,
|
|
61
|
+
});
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
3
66
|
## 0.18.2
|
|
4
67
|
|
|
5
68
|
### Patch Changes
|
|
@@ -4,8 +4,6 @@ order: 0
|
|
|
4
4
|
|
|
5
5
|
import SectionMessage from '@atlaskit/section-message';
|
|
6
6
|
|
|
7
|
-
<!-- I'd like to change this section to be called Drag-and-drop or something, not Core, but still mulling it over. -->
|
|
8
|
-
|
|
9
7
|
This package contains the essential pieces of the system, and is not tied to any JavaScript framework.
|
|
10
8
|
|
|
11
9
|
- The [element adapter](/components/pragmatic-drag-and-drop/adapter/element-adapter) powers drag operations of elements.
|
|
@@ -176,10 +174,6 @@ You can use `setCustomNativeDragPreview` to mount a new element to the page to b
|
|
|
176
174
|
|
|
177
175
|
`setCustomNativeDragPreview` has been designed to work with any view abstraction
|
|
178
176
|
|
|
179
|
-
```ts
|
|
180
|
-
import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/util/set-custom-native-drag-preview';
|
|
181
|
-
```
|
|
182
|
-
|
|
183
177
|
#### Usage example: `react` portals
|
|
184
178
|
|
|
185
179
|
This technique requires your component to be re-rendered, but maintains the current `react` `context`
|
|
@@ -234,7 +228,6 @@ function Item() {
|
|
|
234
228
|
|
|
235
229
|
This technique requires no re-rendering of your component, but does not maintain the current `react` `context`
|
|
236
230
|
|
|
237
|
-
|
|
238
231
|
```tsx
|
|
239
232
|
import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/util/set-custom-native-drag-preview';
|
|
240
233
|
|
|
@@ -254,12 +247,33 @@ draggable({
|
|
|
254
247
|
});
|
|
255
248
|
```
|
|
256
249
|
|
|
257
|
-
####
|
|
250
|
+
#### Offset
|
|
251
|
+
|
|
252
|
+
You can control where the custom native drag preview is placed by using the `getOffset()` argument.
|
|
253
|
+
|
|
254
|
+
You can return an `{x: number, y: number}` object from `getOffset()` which will control where the native drag preview is rendered relative to the users pointer. `{x: 0, y: 0}` represents having the users pointer user the top left corner of the drag preview.
|
|
255
|
+
|
|
256
|
+
For clarity:
|
|
257
|
+
|
|
258
|
+
> `const rect = container.getBoundingClientRect()`
|
|
259
|
+
|
|
260
|
+
- `{x: 0, y: 0}` → top left of the `container` will be under the users pointer **(default)**
|
|
261
|
+
- `{x: rect.width, y: 0}` top right of the `container` will be under the users pointer
|
|
262
|
+
- `{x: rect.width, y: rect.height}` bottom right of the `container` will be under the users pointer
|
|
263
|
+
- `{x: 0, y: rect.height}` bottom left of the `container` will be under the users pointer
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
```ts
|
|
267
|
+
type GetOffsetFn = (args: { container: HTMLElement }) => {x: number, y: number};
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Notes:
|
|
258
271
|
|
|
259
|
-
|
|
272
|
+
- `GetOffsetFn` needs to return `x` and `y` as numbers as that is what the platform requires
|
|
273
|
+
- You cannot use negative values (not supported by browsers). If you want to push the drag preview away from the users pointer, use `offsetFromPointer` (see below)
|
|
274
|
+
- The max offset value for an axis is the `border-box`. Values greater than the `border-box` get trimmed to be the `border-box` value
|
|
260
275
|
|
|
261
|
-
|
|
262
|
-
- `type: 'offset-from-pointer'`: Shift the drag preview away from the users pointer
|
|
276
|
+
`{x: rect.width + 1, y: rect.height + 1}` effectively becomes `{x: rect.width, y: rect.height}`.
|
|
263
277
|
|
|
264
278
|
```tsx
|
|
265
279
|
import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/util/set-custom-native-drag-preview';
|
|
@@ -268,7 +282,11 @@ draggable({
|
|
|
268
282
|
element: myElement,
|
|
269
283
|
onGenerateDragPreview: ({ nativeSetDragImage }) => {
|
|
270
284
|
setCustomNativeDragPreview({
|
|
271
|
-
|
|
285
|
+
// place the (near) top middle of the `container` under the users pointer
|
|
286
|
+
getOffset: () => {
|
|
287
|
+
const rect = container.getBoundingClientRect();
|
|
288
|
+
return { x: rect.width / 2, y: 16 };
|
|
289
|
+
},
|
|
272
290
|
render: function render({ container }) {
|
|
273
291
|
ReactDOM.render(<Preview item={item} />, container);
|
|
274
292
|
return function cleanup() {
|
|
@@ -281,6 +299,51 @@ draggable({
|
|
|
281
299
|
});
|
|
282
300
|
```
|
|
283
301
|
|
|
302
|
+
We have `getOffset()` helpers for `setCustomnativeDragPreview()`:
|
|
303
|
+
|
|
304
|
+
1. `centerUnderPointer`: centers the custom native drag preview under the users cursor
|
|
305
|
+
|
|
306
|
+
```ts
|
|
307
|
+
import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/util/set-custom-native-drag-preview';
|
|
308
|
+
import { centerUnderPointer } from '@atlaskit/pragmatic-drag-and-drop/util/center-under-pointer';
|
|
309
|
+
|
|
310
|
+
draggable({
|
|
311
|
+
element: myElement,
|
|
312
|
+
onGenerateDragPreview: ({ nativeSetDragImage }) => {
|
|
313
|
+
setCustomNativeDragPreview({
|
|
314
|
+
getOffset: centerUnderPointer,
|
|
315
|
+
render: function render({ container }) {
|
|
316
|
+
/* ... */
|
|
317
|
+
},
|
|
318
|
+
nativeSetDragImage,
|
|
319
|
+
});
|
|
320
|
+
},
|
|
321
|
+
});
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
2. `offsetFromPointer`: a cross browser mechanism to push the drag preview away from the users pointer
|
|
325
|
+
|
|
326
|
+
```ts
|
|
327
|
+
import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/util/set-custom-native-drag-preview';
|
|
328
|
+
import { offsetFromPointer } from '@atlaskit/pragmatic-drag-and-drop/util/offset-from-pointer';
|
|
329
|
+
|
|
330
|
+
draggable({
|
|
331
|
+
element: myElement,
|
|
332
|
+
onGenerateDragPreview: ({ nativeSetDragImage }) => {
|
|
333
|
+
setCustomNativeDragPreview({
|
|
334
|
+
// `x` and `y` can be any CSS value
|
|
335
|
+
getOffset: offsetFromPointer({ x: '8px', y: 'calc(var(--grid) * 2)' }),
|
|
336
|
+
render: function render({ container }) {
|
|
337
|
+
/* ... */
|
|
338
|
+
},
|
|
339
|
+
nativeSetDragImage,
|
|
340
|
+
});
|
|
341
|
+
},
|
|
342
|
+
});
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
Note: if you are using css variables inside of your `getOffset()` you need to be sure your css variables are available at the `<body>` element, as the `container` is temporarily mounted as a child of `<body>`
|
|
346
|
+
|
|
284
347
|
### Disable native drag preview
|
|
285
348
|
|
|
286
349
|
In some situations, you might want to disable the native drag preview. The `disableNativeDragPreview` utility does this for all supported browsers and platforms.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "centerUnderPointer", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function get() {
|
|
9
|
+
return _centerUnderPointer.centerUnderPointer;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
var _centerUnderPointer = require("../../util/custom-native-drag-preview/center-under-pointer");
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "offsetFromPointer", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function get() {
|
|
9
|
+
return _offsetFromPointer.offsetFromPointer;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
var _offsetFromPointer = require("../../util/custom-native-drag-preview/offset-from-pointer");
|
|
@@ -9,4 +9,4 @@ Object.defineProperty(exports, "setCustomNativeDragPreview", {
|
|
|
9
9
|
return _setCustomNativeDragPreview.setCustomNativeDragPreview;
|
|
10
10
|
}
|
|
11
11
|
});
|
|
12
|
-
var _setCustomNativeDragPreview = require("../../util/set-custom-native-drag-preview");
|
|
12
|
+
var _setCustomNativeDragPreview = require("../../util/custom-native-drag-preview/set-custom-native-drag-preview");
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.centerUnderPointer = void 0;
|
|
7
|
+
var centerUnderPointer = function centerUnderPointer(_ref) {
|
|
8
|
+
var container = _ref.container;
|
|
9
|
+
var rect = container.getBoundingClientRect();
|
|
10
|
+
return {
|
|
11
|
+
x: rect.width / 2,
|
|
12
|
+
y: rect.height / 2
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
exports.centerUnderPointer = centerUnderPointer;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.offsetFromPointer = offsetFromPointer;
|
|
7
|
+
/** Any valid CSS string value
|
|
8
|
+
* @example `calc(var(--grid) * 2)
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
function offsetFromPointer(point) {
|
|
12
|
+
return function (_ref) {
|
|
13
|
+
var container = _ref.container;
|
|
14
|
+
// Only reliable cross browser technique found to push a
|
|
15
|
+
// drag preview away from the cursor is to use transparent borders on the container
|
|
16
|
+
Object.assign(container.style, {
|
|
17
|
+
borderLeft: "".concat(point.x, " solid transparent"),
|
|
18
|
+
borderTop: "".concat(point.y, " solid transparent")
|
|
19
|
+
});
|
|
20
|
+
return {
|
|
21
|
+
x: 0,
|
|
22
|
+
y: 0
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -4,46 +4,19 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.setCustomNativeDragPreview = setCustomNativeDragPreview;
|
|
7
|
-
var _elementAdapter = require("
|
|
7
|
+
var _elementAdapter = require("../../adapter/element-adapter");
|
|
8
8
|
/** A function to remove the element that has been added to the `container`.
|
|
9
9
|
* @example () => ReactDOM.unmountComponentAtNode(container)
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
/** A function that will render a preview element into a `container` `HTMLElement` */
|
|
13
13
|
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
*
|
|
21
|
-
* `type: 'center'`: Place the center of the drag preview user the users pointer
|
|
22
|
-
*
|
|
23
|
-
* `type: 'offset-from-pointer'`: Shift the drag preview away from the users pointer
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
function setImage(_ref) {
|
|
27
|
-
var container = _ref.container,
|
|
28
|
-
placement = _ref.placement,
|
|
29
|
-
nativeSetDragImage = _ref.nativeSetDragImage;
|
|
30
|
-
if ((placement === null || placement === void 0 ? void 0 : placement.type) === 'center') {
|
|
31
|
-
var box = container.getBoundingClientRect();
|
|
32
|
-
nativeSetDragImage === null || nativeSetDragImage === void 0 ? void 0 : nativeSetDragImage(container, box.width / 2, box.height / 2);
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
if ((placement === null || placement === void 0 ? void 0 : placement.type) === 'offset-from-pointer') {
|
|
36
|
-
// Using a transparent border to push the drag preview away
|
|
37
|
-
// from the user's pointer.
|
|
38
|
-
// In Chrome and Safari we could use `padding`:
|
|
39
|
-
// padding: 'var(--grid)',
|
|
40
|
-
// But it does not work in Firefox which trims the padding (or inner margin)
|
|
41
|
-
Object.assign(container.style, {
|
|
42
|
-
borderLeft: "".concat(placement.x, " solid transparent"),
|
|
43
|
-
borderTop: "".concat(placement.y, " solid transparent")
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
nativeSetDragImage === null || nativeSetDragImage === void 0 ? void 0 : nativeSetDragImage(container, 0, 0);
|
|
14
|
+
/** By default we use the build in values for the native drag preview: {x: 0, y: 0} */
|
|
15
|
+
function defaultOffset() {
|
|
16
|
+
return {
|
|
17
|
+
x: 0,
|
|
18
|
+
y: 0
|
|
19
|
+
};
|
|
47
20
|
}
|
|
48
21
|
|
|
49
22
|
/** This function provides the ability to mount an element for it to be used as the native drag preview
|
|
@@ -61,10 +34,11 @@ function setImage(_ref) {
|
|
|
61
34
|
* },
|
|
62
35
|
* });
|
|
63
36
|
*/
|
|
64
|
-
function setCustomNativeDragPreview(
|
|
65
|
-
var render =
|
|
66
|
-
nativeSetDragImage =
|
|
67
|
-
|
|
37
|
+
function setCustomNativeDragPreview(_ref) {
|
|
38
|
+
var render = _ref.render,
|
|
39
|
+
nativeSetDragImage = _ref.nativeSetDragImage,
|
|
40
|
+
_ref$getOffset = _ref.getOffset,
|
|
41
|
+
getOffset = _ref$getOffset === void 0 ? defaultOffset : _ref$getOffset;
|
|
68
42
|
var container = document.createElement('div');
|
|
69
43
|
Object.assign(container.style, {
|
|
70
44
|
// Ensuring we don't cause reflow when adding the element to the page
|
|
@@ -90,11 +64,10 @@ function setCustomNativeDragPreview(_ref2) {
|
|
|
90
64
|
var unmount = render({
|
|
91
65
|
container: container
|
|
92
66
|
});
|
|
93
|
-
|
|
94
|
-
container: container
|
|
95
|
-
placement: placement,
|
|
96
|
-
nativeSetDragImage: nativeSetDragImage
|
|
67
|
+
var previewOffset = getOffset({
|
|
68
|
+
container: container
|
|
97
69
|
});
|
|
70
|
+
nativeSetDragImage === null || nativeSetDragImage === void 0 ? void 0 : nativeSetDragImage(container, previewOffset.x, previewOffset.y);
|
|
98
71
|
function cleanup() {
|
|
99
72
|
unbindMonitor();
|
|
100
73
|
unmount === null || unmount === void 0 ? void 0 : unmount();
|
package/dist/cjs/version.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { centerUnderPointer } from '../../util/custom-native-drag-preview/center-under-pointer';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { offsetFromPointer } from '../../util/custom-native-drag-preview/offset-from-pointer';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { setCustomNativeDragPreview } from '../../util/set-custom-native-drag-preview';
|
|
1
|
+
export { setCustomNativeDragPreview } from '../../util/custom-native-drag-preview/set-custom-native-drag-preview';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Any valid CSS string value
|
|
2
|
+
* @example `calc(var(--grid) * 2)
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export function offsetFromPointer(point) {
|
|
6
|
+
return ({
|
|
7
|
+
container
|
|
8
|
+
}) => {
|
|
9
|
+
// Only reliable cross browser technique found to push a
|
|
10
|
+
// drag preview away from the cursor is to use transparent borders on the container
|
|
11
|
+
Object.assign(container.style, {
|
|
12
|
+
borderLeft: `${point.x} solid transparent`,
|
|
13
|
+
borderTop: `${point.y} solid transparent`
|
|
14
|
+
});
|
|
15
|
+
return {
|
|
16
|
+
x: 0,
|
|
17
|
+
y: 0
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { monitorForElements } from '
|
|
1
|
+
import { monitorForElements } from '../../adapter/element-adapter';
|
|
2
2
|
|
|
3
3
|
/** A function to remove the element that has been added to the `container`.
|
|
4
4
|
* @example () => ReactDOM.unmountComponentAtNode(container)
|
|
@@ -6,40 +6,12 @@ import { monitorForElements } from '../adapter/element-adapter';
|
|
|
6
6
|
|
|
7
7
|
/** A function that will render a preview element into a `container` `HTMLElement` */
|
|
8
8
|
|
|
9
|
-
/**
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
*
|
|
16
|
-
* `type: 'center'`: Place the center of the drag preview user the users pointer
|
|
17
|
-
*
|
|
18
|
-
* `type: 'offset-from-pointer'`: Shift the drag preview away from the users pointer
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
function setImage({
|
|
22
|
-
container,
|
|
23
|
-
placement,
|
|
24
|
-
nativeSetDragImage
|
|
25
|
-
}) {
|
|
26
|
-
if ((placement === null || placement === void 0 ? void 0 : placement.type) === 'center') {
|
|
27
|
-
const box = container.getBoundingClientRect();
|
|
28
|
-
nativeSetDragImage === null || nativeSetDragImage === void 0 ? void 0 : nativeSetDragImage(container, box.width / 2, box.height / 2);
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
if ((placement === null || placement === void 0 ? void 0 : placement.type) === 'offset-from-pointer') {
|
|
32
|
-
// Using a transparent border to push the drag preview away
|
|
33
|
-
// from the user's pointer.
|
|
34
|
-
// In Chrome and Safari we could use `padding`:
|
|
35
|
-
// padding: 'var(--grid)',
|
|
36
|
-
// But it does not work in Firefox which trims the padding (or inner margin)
|
|
37
|
-
Object.assign(container.style, {
|
|
38
|
-
borderLeft: `${placement.x} solid transparent`,
|
|
39
|
-
borderTop: `${placement.y} solid transparent`
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
nativeSetDragImage === null || nativeSetDragImage === void 0 ? void 0 : nativeSetDragImage(container, 0, 0);
|
|
9
|
+
/** By default we use the build in values for the native drag preview: {x: 0, y: 0} */
|
|
10
|
+
function defaultOffset() {
|
|
11
|
+
return {
|
|
12
|
+
x: 0,
|
|
13
|
+
y: 0
|
|
14
|
+
};
|
|
43
15
|
}
|
|
44
16
|
|
|
45
17
|
/** This function provides the ability to mount an element for it to be used as the native drag preview
|
|
@@ -60,7 +32,7 @@ function setImage({
|
|
|
60
32
|
export function setCustomNativeDragPreview({
|
|
61
33
|
render,
|
|
62
34
|
nativeSetDragImage,
|
|
63
|
-
|
|
35
|
+
getOffset = defaultOffset
|
|
64
36
|
}) {
|
|
65
37
|
const container = document.createElement('div');
|
|
66
38
|
Object.assign(container.style, {
|
|
@@ -87,11 +59,10 @@ export function setCustomNativeDragPreview({
|
|
|
87
59
|
const unmount = render({
|
|
88
60
|
container
|
|
89
61
|
});
|
|
90
|
-
|
|
91
|
-
container
|
|
92
|
-
placement,
|
|
93
|
-
nativeSetDragImage
|
|
62
|
+
const previewOffset = getOffset({
|
|
63
|
+
container
|
|
94
64
|
});
|
|
65
|
+
nativeSetDragImage === null || nativeSetDragImage === void 0 ? void 0 : nativeSetDragImage(container, previewOffset.x, previewOffset.y);
|
|
95
66
|
function cleanup() {
|
|
96
67
|
unbindMonitor();
|
|
97
68
|
unmount === null || unmount === void 0 ? void 0 : unmount();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/es2019/version.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { centerUnderPointer } from '../../util/custom-native-drag-preview/center-under-pointer';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { offsetFromPointer } from '../../util/custom-native-drag-preview/offset-from-pointer';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { setCustomNativeDragPreview } from '../../util/set-custom-native-drag-preview';
|
|
1
|
+
export { setCustomNativeDragPreview } from '../../util/custom-native-drag-preview/set-custom-native-drag-preview';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** Any valid CSS string value
|
|
2
|
+
* @example `calc(var(--grid) * 2)
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export function offsetFromPointer(point) {
|
|
6
|
+
return function (_ref) {
|
|
7
|
+
var container = _ref.container;
|
|
8
|
+
// Only reliable cross browser technique found to push a
|
|
9
|
+
// drag preview away from the cursor is to use transparent borders on the container
|
|
10
|
+
Object.assign(container.style, {
|
|
11
|
+
borderLeft: "".concat(point.x, " solid transparent"),
|
|
12
|
+
borderTop: "".concat(point.y, " solid transparent")
|
|
13
|
+
});
|
|
14
|
+
return {
|
|
15
|
+
x: 0,
|
|
16
|
+
y: 0
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { monitorForElements } from '
|
|
1
|
+
import { monitorForElements } from '../../adapter/element-adapter';
|
|
2
2
|
|
|
3
3
|
/** A function to remove the element that has been added to the `container`.
|
|
4
4
|
* @example () => ReactDOM.unmountComponentAtNode(container)
|
|
@@ -6,39 +6,12 @@ import { monitorForElements } from '../adapter/element-adapter';
|
|
|
6
6
|
|
|
7
7
|
/** A function that will render a preview element into a `container` `HTMLElement` */
|
|
8
8
|
|
|
9
|
-
/**
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
*
|
|
16
|
-
* `type: 'center'`: Place the center of the drag preview user the users pointer
|
|
17
|
-
*
|
|
18
|
-
* `type: 'offset-from-pointer'`: Shift the drag preview away from the users pointer
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
function setImage(_ref) {
|
|
22
|
-
var container = _ref.container,
|
|
23
|
-
placement = _ref.placement,
|
|
24
|
-
nativeSetDragImage = _ref.nativeSetDragImage;
|
|
25
|
-
if ((placement === null || placement === void 0 ? void 0 : placement.type) === 'center') {
|
|
26
|
-
var box = container.getBoundingClientRect();
|
|
27
|
-
nativeSetDragImage === null || nativeSetDragImage === void 0 ? void 0 : nativeSetDragImage(container, box.width / 2, box.height / 2);
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
if ((placement === null || placement === void 0 ? void 0 : placement.type) === 'offset-from-pointer') {
|
|
31
|
-
// Using a transparent border to push the drag preview away
|
|
32
|
-
// from the user's pointer.
|
|
33
|
-
// In Chrome and Safari we could use `padding`:
|
|
34
|
-
// padding: 'var(--grid)',
|
|
35
|
-
// But it does not work in Firefox which trims the padding (or inner margin)
|
|
36
|
-
Object.assign(container.style, {
|
|
37
|
-
borderLeft: "".concat(placement.x, " solid transparent"),
|
|
38
|
-
borderTop: "".concat(placement.y, " solid transparent")
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
nativeSetDragImage === null || nativeSetDragImage === void 0 ? void 0 : nativeSetDragImage(container, 0, 0);
|
|
9
|
+
/** By default we use the build in values for the native drag preview: {x: 0, y: 0} */
|
|
10
|
+
function defaultOffset() {
|
|
11
|
+
return {
|
|
12
|
+
x: 0,
|
|
13
|
+
y: 0
|
|
14
|
+
};
|
|
42
15
|
}
|
|
43
16
|
|
|
44
17
|
/** This function provides the ability to mount an element for it to be used as the native drag preview
|
|
@@ -56,10 +29,11 @@ function setImage(_ref) {
|
|
|
56
29
|
* },
|
|
57
30
|
* });
|
|
58
31
|
*/
|
|
59
|
-
export function setCustomNativeDragPreview(
|
|
60
|
-
var render =
|
|
61
|
-
nativeSetDragImage =
|
|
62
|
-
|
|
32
|
+
export function setCustomNativeDragPreview(_ref) {
|
|
33
|
+
var render = _ref.render,
|
|
34
|
+
nativeSetDragImage = _ref.nativeSetDragImage,
|
|
35
|
+
_ref$getOffset = _ref.getOffset,
|
|
36
|
+
getOffset = _ref$getOffset === void 0 ? defaultOffset : _ref$getOffset;
|
|
63
37
|
var container = document.createElement('div');
|
|
64
38
|
Object.assign(container.style, {
|
|
65
39
|
// Ensuring we don't cause reflow when adding the element to the page
|
|
@@ -85,11 +59,10 @@ export function setCustomNativeDragPreview(_ref2) {
|
|
|
85
59
|
var unmount = render({
|
|
86
60
|
container: container
|
|
87
61
|
});
|
|
88
|
-
|
|
89
|
-
container: container
|
|
90
|
-
placement: placement,
|
|
91
|
-
nativeSetDragImage: nativeSetDragImage
|
|
62
|
+
var previewOffset = getOffset({
|
|
63
|
+
container: container
|
|
92
64
|
});
|
|
65
|
+
nativeSetDragImage === null || nativeSetDragImage === void 0 ? void 0 : nativeSetDragImage(container, previewOffset.x, previewOffset.y);
|
|
93
66
|
function cleanup() {
|
|
94
67
|
unbindMonitor();
|
|
95
68
|
unmount === null || unmount === void 0 ? void 0 : unmount();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/esm/version.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { centerUnderPointer } from '../../util/custom-native-drag-preview/center-under-pointer';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { offsetFromPointer } from '../../util/custom-native-drag-preview/offset-from-pointer';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { setCustomNativeDragPreview } from '../../util/set-custom-native-drag-preview';
|
|
1
|
+
export { setCustomNativeDragPreview } from '../../util/custom-native-drag-preview/set-custom-native-drag-preview';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { ElementEventPayloadMap } from '
|
|
1
|
+
import { ElementEventPayloadMap } from '../../adapter/element-adapter';
|
|
2
|
+
import type { GetOffsetFn } from './types';
|
|
2
3
|
/** A function to remove the element that has been added to the `container`.
|
|
3
4
|
* @example () => ReactDOM.unmountComponentAtNode(container)
|
|
4
5
|
*/
|
|
@@ -11,24 +12,6 @@ type RenderFn = ({ container, }: {
|
|
|
11
12
|
*/
|
|
12
13
|
container: HTMLElement;
|
|
13
14
|
}) => CleanupFn | void;
|
|
14
|
-
/** Any valid CSS string value
|
|
15
|
-
* @example `calc(var(--grid) * 2)
|
|
16
|
-
*/
|
|
17
|
-
type CSSValue = string;
|
|
18
|
-
/**
|
|
19
|
-
* Where to place the custom drag preview
|
|
20
|
-
*
|
|
21
|
-
* `type: 'center'`: Place the center of the drag preview user the users pointer
|
|
22
|
-
*
|
|
23
|
-
* `type: 'offset-from-pointer'`: Shift the drag preview away from the users pointer
|
|
24
|
-
*/
|
|
25
|
-
type Placement = {
|
|
26
|
-
type: 'center';
|
|
27
|
-
} | {
|
|
28
|
-
type: 'offset-from-pointer';
|
|
29
|
-
x: CSSValue;
|
|
30
|
-
y: CSSValue;
|
|
31
|
-
};
|
|
32
15
|
/** This function provides the ability to mount an element for it to be used as the native drag preview
|
|
33
16
|
*
|
|
34
17
|
* @example
|
|
@@ -44,8 +27,8 @@ type Placement = {
|
|
|
44
27
|
* },
|
|
45
28
|
* });
|
|
46
29
|
*/
|
|
47
|
-
export declare function setCustomNativeDragPreview({ render, nativeSetDragImage,
|
|
48
|
-
|
|
30
|
+
export declare function setCustomNativeDragPreview({ render, nativeSetDragImage, getOffset, }: {
|
|
31
|
+
getOffset?: GetOffsetFn;
|
|
49
32
|
render: RenderFn;
|
|
50
33
|
nativeSetDragImage: ElementEventPayloadMap['onGenerateDragPreview']['nativeSetDragImage'];
|
|
51
34
|
}): void;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Position } from '../../internal-types';
|
|
2
|
+
/** A function that will push the position of native drag preview.
|
|
3
|
+
*
|
|
4
|
+
* `{x: 0, y: 0}` represents having the users pointer user the top left corner of the drag preview.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* `const rect = container.getBoundingClientRect()`
|
|
8
|
+
*
|
|
9
|
+
* - `{x: 0, y: 0}` → top left of the `container` will be under the users pointer **(default)**
|
|
10
|
+
* - `{x: rect.width, y: 0}` → top right of the `container` will be under the users pointer
|
|
11
|
+
* - `{x: rect.width, y: rect.height}` → bottom right of the `container` will be under the users pointer
|
|
12
|
+
* - `{x: 0, y: rect.height}`→ bottom left of the `container` will be under the users pointer
|
|
13
|
+
*/
|
|
14
|
+
export type GetOffsetFn = (args: {
|
|
15
|
+
container: HTMLElement;
|
|
16
|
+
}) => Position;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { centerUnderPointer } from '../../util/custom-native-drag-preview/center-under-pointer';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { offsetFromPointer } from '../../util/custom-native-drag-preview/offset-from-pointer';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { setCustomNativeDragPreview } from '../../util/set-custom-native-drag-preview';
|
|
1
|
+
export { setCustomNativeDragPreview } from '../../util/custom-native-drag-preview/set-custom-native-drag-preview';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { ElementEventPayloadMap } from '
|
|
1
|
+
import { ElementEventPayloadMap } from '../../adapter/element-adapter';
|
|
2
|
+
import type { GetOffsetFn } from './types';
|
|
2
3
|
/** A function to remove the element that has been added to the `container`.
|
|
3
4
|
* @example () => ReactDOM.unmountComponentAtNode(container)
|
|
4
5
|
*/
|
|
@@ -11,24 +12,6 @@ type RenderFn = ({ container, }: {
|
|
|
11
12
|
*/
|
|
12
13
|
container: HTMLElement;
|
|
13
14
|
}) => CleanupFn | void;
|
|
14
|
-
/** Any valid CSS string value
|
|
15
|
-
* @example `calc(var(--grid) * 2)
|
|
16
|
-
*/
|
|
17
|
-
type CSSValue = string;
|
|
18
|
-
/**
|
|
19
|
-
* Where to place the custom drag preview
|
|
20
|
-
*
|
|
21
|
-
* `type: 'center'`: Place the center of the drag preview user the users pointer
|
|
22
|
-
*
|
|
23
|
-
* `type: 'offset-from-pointer'`: Shift the drag preview away from the users pointer
|
|
24
|
-
*/
|
|
25
|
-
type Placement = {
|
|
26
|
-
type: 'center';
|
|
27
|
-
} | {
|
|
28
|
-
type: 'offset-from-pointer';
|
|
29
|
-
x: CSSValue;
|
|
30
|
-
y: CSSValue;
|
|
31
|
-
};
|
|
32
15
|
/** This function provides the ability to mount an element for it to be used as the native drag preview
|
|
33
16
|
*
|
|
34
17
|
* @example
|
|
@@ -44,8 +27,8 @@ type Placement = {
|
|
|
44
27
|
* },
|
|
45
28
|
* });
|
|
46
29
|
*/
|
|
47
|
-
export declare function setCustomNativeDragPreview({ render, nativeSetDragImage,
|
|
48
|
-
|
|
30
|
+
export declare function setCustomNativeDragPreview({ render, nativeSetDragImage, getOffset, }: {
|
|
31
|
+
getOffset?: GetOffsetFn;
|
|
49
32
|
render: RenderFn;
|
|
50
33
|
nativeSetDragImage: ElementEventPayloadMap['onGenerateDragPreview']['nativeSetDragImage'];
|
|
51
34
|
}): void;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Position } from '../../internal-types';
|
|
2
|
+
/** A function that will push the position of native drag preview.
|
|
3
|
+
*
|
|
4
|
+
* `{x: 0, y: 0}` represents having the users pointer user the top left corner of the drag preview.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* `const rect = container.getBoundingClientRect()`
|
|
8
|
+
*
|
|
9
|
+
* - `{x: 0, y: 0}` → top left of the `container` will be under the users pointer **(default)**
|
|
10
|
+
* - `{x: rect.width, y: 0}` → top right of the `container` will be under the users pointer
|
|
11
|
+
* - `{x: rect.width, y: rect.height}` → bottom right of the `container` will be under the users pointer
|
|
12
|
+
* - `{x: 0, y: rect.height}`→ bottom left of the `container` will be under the users pointer
|
|
13
|
+
*/
|
|
14
|
+
export type GetOffsetFn = (args: {
|
|
15
|
+
container: HTMLElement;
|
|
16
|
+
}) => Position;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/pragmatic-drag-and-drop",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"description": "The core Pragmatic drag and drop framework, optimized for performance.",
|
|
5
5
|
"repository": "https://bitbucket.org/atlassian/atlassian-frontend-mirror",
|
|
6
6
|
"author": "Atlassian Pty Ltd",
|
|
@@ -44,6 +44,8 @@
|
|
|
44
44
|
"./util/once": "./src/entry-point/util/once.ts",
|
|
45
45
|
"./util/reorder": "./src/entry-point/util/reorder.ts",
|
|
46
46
|
"./util/set-custom-native-drag-preview": "./src/entry-point/util/set-custom-native-drag-preview.ts",
|
|
47
|
+
"./util/offset-from-pointer": "./src/entry-point/util/offset-from-pointer.ts",
|
|
48
|
+
"./util/center-under-pointer": "./src/entry-point/util/center-under-pointer.ts",
|
|
47
49
|
"./util/disable-native-drag-preview": "./src/entry-point/util/disable-native-drag-preview.ts",
|
|
48
50
|
"./util/scroll-just-enough-into-view": "./src/entry-point/util/scroll-just-enough-into-view.ts",
|
|
49
51
|
"./experimental/cross-window-element-adapter": "./src/entry-point/experimental/cross-with-element-adapter.ts"
|
|
@@ -54,7 +56,7 @@
|
|
|
54
56
|
"raf-schd": "^4.0.3"
|
|
55
57
|
},
|
|
56
58
|
"devDependencies": {
|
|
57
|
-
"@atlaskit/tokens": "^1.
|
|
59
|
+
"@atlaskit/tokens": "^1.6.0",
|
|
58
60
|
"@atlaskit/visual-regression": "*",
|
|
59
61
|
"@atlassian/atlassian-frontend-prettier-config-1.0.0": "npm:@atlassian/atlassian-frontend-prettier-config@1.0.0",
|
|
60
62
|
"@emotion/react": "^11.7.1",
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@atlaskit/pragmatic-drag-and-drop/util/center-under-pointer",
|
|
3
|
+
"main": "../../dist/cjs/entry-point/util/center-under-pointer.js",
|
|
4
|
+
"module": "../../dist/esm/entry-point/util/center-under-pointer.js",
|
|
5
|
+
"module:es2019": "../../dist/es2019/entry-point/util/center-under-pointer.js",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"types": "../../dist/types/entry-point/util/center-under-pointer.d.ts",
|
|
8
|
+
"typesVersions": {
|
|
9
|
+
">=4.5 <4.9": {
|
|
10
|
+
"*": [
|
|
11
|
+
"../../dist/types-ts4.5/entry-point/util/center-under-pointer.d.ts"
|
|
12
|
+
]
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@atlaskit/pragmatic-drag-and-drop/util/offset-from-pointer",
|
|
3
|
+
"main": "../../dist/cjs/entry-point/util/offset-from-pointer.js",
|
|
4
|
+
"module": "../../dist/esm/entry-point/util/offset-from-pointer.js",
|
|
5
|
+
"module:es2019": "../../dist/es2019/entry-point/util/offset-from-pointer.js",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"types": "../../dist/types/entry-point/util/offset-from-pointer.d.ts",
|
|
8
|
+
"typesVersions": {
|
|
9
|
+
">=4.5 <4.9": {
|
|
10
|
+
"*": [
|
|
11
|
+
"../../dist/types-ts4.5/entry-point/util/offset-from-pointer.d.ts"
|
|
12
|
+
]
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|