Skip to content

Commit

Permalink
feat(ui5-list,ui5-tree): make drag&drop feature public (#8904)
Browse files Browse the repository at this point in the history
The drag&drop feature for both `ui5-tree` and `ui5-list` components is now public. 
Updated documentation and new samples have been added to assist with implementation.

Related to #8461, #7887
  • Loading branch information
yanaminkova authored May 16, 2024
1 parent 70dc2a6 commit 60b8038
Show file tree
Hide file tree
Showing 13 changed files with 273 additions and 1 deletion.
9 changes: 9 additions & 0 deletions packages/main/src/CustomListItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ import customListItemCss from "./generated/themes/CustomListItem.css.js";
styles: [ListItem.styles, customListItemCss],
})
class CustomListItem extends ListItem {
/**
* Defines whether the item is movable.
* @default false
* @public
* @since 2.0.0
*/
@property({ type: Boolean })
movable!: boolean;

/**
* Defines the text alternative of the component.
*
Expand Down
46 changes: 46 additions & 0 deletions packages/main/src/List.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,52 @@ type ListItemClickEventDetail = {
item: { type: HTMLElement },
},
})

/**
* Fired when a movable list item is moved over a potential drop target during a dragging operation.
*
* If the new position is valid, prevent the default action of the event using `preventDefault()`.
* @param {object} source Contains information about the moved element under `element` property.
* @param {object} destination Contains information about the destination of the moved element. Has `element` and `placement` properties.
* @public
* @since 2.0.0
* @allowPreventDefault
*/

@event<ListMoveEventDetail>("move-over", {
detail: {
/**
* @public
*/
source: { type: Object },
/**
* @public
*/
destination: { type: Object },
},
})

/**
* Fired when a movable list item is dropped onto a drop target.
*
* **Note:** `move` event is fired only if there was a preceding `move-over` with prevented default action.
* @param {object} source Contains information about the moved element under `element` property.
* @param {object} destination Contains information about the destination of the moved element. Has `element` and `placement` properties.
* @public
* @allowPreventDefault
*/
@event<ListMoveEventDetail>("move", {
detail: {
/**
* @public
*/
source: { type: Object },
/**
* @public
*/
destination: { type: Object },
},
})
class List extends UI5Element {
/**
* Defines the component header text.
Expand Down
1 change: 1 addition & 0 deletions packages/main/src/ListItemBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class ListItemBase extends UI5Element implements ITabbable {
* Defines whether the item is movable.
* @default false
* @private
* @since 2.0.0
*/
@property({ type: Boolean })
movable!: boolean;
Expand Down
9 changes: 9 additions & 0 deletions packages/main/src/StandardListItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,15 @@ class StandardListItem extends ListItem implements IAccessibleListItem {
@property({ type: ValueState, defaultValue: ValueState.None })
additionalTextState!: `${ValueState}`;

/**
* Defines whether the item is movable.
* @default false
* @public
* @since 2.0.0
*/
@property({ type: Boolean })
movable!: boolean;

/**
* Defines the text alternative of the component.
* Note: If not provided a default text alternative will be set, if present.
Expand Down
9 changes: 9 additions & 0 deletions packages/main/src/TreeItemBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,15 @@ class TreeItemBase extends ListItem {
@property({ type: Boolean })
expanded!: boolean;

/**
* Defines whether the item is movable.
* @default false
* @public
* @since 2.0.0
*/
@property({ type: Boolean })
movable!: boolean;

/**
* Defines whether the selection of a tree node is displayed as partially selected.
*
Expand Down
8 changes: 7 additions & 1 deletion packages/website/docs/_components_pages/main/List/List.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Modes from "../../../_samples/main/List/Modes/Modes.md";
import NoData from "../../../_samples/main/List/NoData/NoData.md";
import GroupHeaders from "../../../_samples/main/List/GroupHeaders/GroupHeaders.md";
import SeparationTypes from "../../../_samples/main/List/SeparationTypes/SeparationTypes.md";
import DragAndDrop from "../../../_samples/main/List/DragAndDrop/DragAndDrop.md";

<%COMPONENT_OVERVIEW%>

Expand Down Expand Up @@ -48,4 +49,9 @@ The <b>The ListItemGroup</b> can be used to start group section and implement gr
### Separators
The <b>separators</b> options (<b>All</b>, <b>Inner</b>, <b>None</b>) allows the outer lines (Inner) or all the lines (None) to be hidden.

<SeparationTypes />
<SeparationTypes />

### Drag And Drop
The list items are draggable through the use of the <b>movable</b> property on <b>ListItem</b>.

<DragAndDrop />
6 changes: 6 additions & 0 deletions packages/website/docs/_components_pages/main/Tree/Tree.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ slug: ../../Tree

import Basic from "../../../_samples/main/Tree/Basic/Basic.md";
import CustomTreeItems from "../../../_samples/main/Tree/CustomTreeItems/CustomTreeItems.md";
import DragAndDrop from "../../../_samples/main/Tree/DragAndDrop/DragAndDrop.md";

<%COMPONENT_OVERVIEW%>

Expand All @@ -16,3 +17,8 @@ import CustomTreeItems from "../../../_samples/main/Tree/CustomTreeItems/CustomT

### Custom Tree Items
<CustomTreeItems />

### Drag And Drop
The tree items are draggable through the use of the <b>movable</b> property on <b>TreeItem</b>.

<DragAndDrop />
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import html from '!!raw-loader!./sample.html';
import js from '!!raw-loader!./main.js';

<Editor html={html} js={js} />
45 changes: 45 additions & 0 deletions packages/website/docs/_samples/main/List/DragAndDrop/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import "@ui5/webcomponents/dist/List.js";
import "@ui5/webcomponents/dist/StandardListItem.js";

import "@ui5/webcomponents-icons/dist/checklist-item.js";

const list = document.getElementById('listDnd1');
const handleBeforeItemMove = (e) => {
const { destination, source } = e.detail;

if (destination.placement === 'Before' || destination.placement === 'After') {
e.preventDefault();
}

};

const handleMoveOver = (e) => {
const { destination, source } = e.detail;

if (!list.contains(source.element)) {
return;
}

handleBeforeItemMove(e);
};

const handleMove = (e) => {
const { destination, source } = e.detail;
const parent = destination.element.closest('[ui5-list]');

if (destination.placement === 'Before') {
parent.insertBefore(source.element, destination.element);
} else if (destination.placement === 'After') {
const nextElement = Array.from(parent.children).at(
Array.from(parent.children).indexOf(destination.element) + 1
);

parent.insertBefore(source.element, nextElement);
} else if (destination.placement === 'On') {
destination.element.prepend(source.element);
}
};

list.addEventListener('move-over', handleMoveOver);
list.addEventListener('move', handleMove);

27 changes: 27 additions & 0 deletions packages/website/docs/_samples/main/List/DragAndDrop/sample.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!-- playground-fold -->
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sample</title>
</head>

<body style="background-color: var(--sapBackgroundColor)">
<!-- playground-fold-end -->

<ui5-list id="listDnd1">
<ui5-li icon="checklist-item" movable>Item #1</ui5-li>
<ui5-li icon="checklist-item" movable>Item #2</ui5-li>
<ui5-li icon="checklist-item" movable>Item #3</ui5-li>
<ui5-li icon="checklist-item" movable>Item #4</ui5-li>
<ui5-li icon="checklist-item" movable>Item #5</ui5-li>
</ui5-list>

<!-- playground-fold -->
<script type="module" src="main.js"></script>
</body>

</html>
<!-- playground-fold-end -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import html from '!!raw-loader!./sample.html';
import js from '!!raw-loader!./main.js';

<Editor html={html} js={js} />
55 changes: 55 additions & 0 deletions packages/website/docs/_samples/main/Tree/DragAndDrop/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import "@ui5/webcomponents/dist/Tree.js";
import "@ui5/webcomponents/dist/TreeItem.js";
import "@ui5/webcomponents/dist/Title.js";
import "@ui5/webcomponents/dist/Label.js";


const tree = document.getElementById("tree");
const handleBeforeItemMove = (e) => {
const { destination, source } = e.detail;

if (destination.placement === "Before" || destination.placement === "After") {
e.preventDefault();
}

if (destination.placement === "On" && "allowsNesting" in destination.element.dataset) {
e.preventDefault();
}

console.log(`Moving "${source.element.text}" ${destination.placement.toLowerCase()} "${destination.element.text}"`);
};

const handleMoveOver = (e) => {
const { destination, source } = e.detail;

if (!tree.contains(source.element)) {
return;
}

handleBeforeItemMove(e);
};

const handleMove = (e) => {
const { destination, source } = e.detail;
const parent = destination.element.parentNode.closest("[ui5-tree-item]") ||
destination.element.closest("[ui5-tree]");

if (destination.placement === "Before") {
parent.insertBefore(
source.element,
destination.element
);
} else if (destination.placement === "After") {
const nextElement = Array.from(parent.children).at(Array.from(parent.children).indexOf(destination.element) + 1);

parent.insertBefore(
source.element,
nextElement,
);
} else if (destination.placement === "On") {
destination.element.prepend(source.element);
}
};

tree.addEventListener("move-over", handleMoveOver);
tree.addEventListener("move", handleMove);
51 changes: 51 additions & 0 deletions packages/website/docs/_samples/main/Tree/DragAndDrop/sample.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<!-- playground-fold -->
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sample</title>
</head>

<body style="background-color: var(--sapBackgroundColor)">
<!-- playground-fold-end -->
<ui5-tree id="tree" no-data-text="No data" mode="MultiSelect" accessible-name="Tree with accessibleName">

<ui5-tree-item movable text="Tree 1" icon="paste" additional-text="Available" indeterminate selected additional-text-state="Information" accessible-name="Tree item with accessibleName">
<ui5-title slot="content">
<ui5-label>Tree 1</ui5-label>
<ui5-label>Tree 1</ui5-label>
</ui5-title>

<ui5-tree-item movable expanded text="Tree 1.1" additional-text="Re-stock" additional-text-state="Negative" indeterminate selected>
<ui5-tree-item movable text="Tree 1.1.1" additional-text="Required" additional-text-state="Critical" selected></ui5-tree-item>
<ui5-tree-item movable text="Tree 1.1.2" additional-text="Available" additional-text-state="Positive"></ui5-tree-item>
</ui5-tree-item>
</ui5-tree-item>

<ui5-tree-item movable data-allows-nesting text="Tree 2(Allows Nesting)" icon="copy">
<ui5-tree-item movable id="firstCollapsedItem" text="Tree 2.1">
<ui5-tree-item movable text="Tree 2.1.1"></ui5-tree-item>
<ui5-tree-item movable text="Tree 2.1.2">
<ui5-tree-item movable text="Tree 2.1.2.1"></ui5-tree-item>
<ui5-tree-item movable text="Tree 2.1.2.2"></ui5-tree-item>
<ui5-tree-item movable text="Tree 2.1.2.3"></ui5-tree-item>
<ui5-tree-item movable text="Tree 2.1.2.5"></ui5-tree-item>
</ui5-tree-item>
</ui5-tree-item>
<ui5-tree-item movable text="Tree 2.2"></ui5-tree-item>
<ui5-tree-item movable text="Tree 2.3"></ui5-tree-item>
</ui5-tree-item>

<ui5-tree-item movable text="Tree 3 (no icon)">
</ui5-tree-item>

</ui5-tree>

<!-- playground-fold -->
<script type="module" src="main.js"></script>
</body>

</html>
<!-- playground-fold-end -->

0 comments on commit 60b8038

Please sign in to comment.