diff --git a/.eslintrc.js b/.eslintrc.js index 1581295..b53d625 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -43,6 +43,7 @@ module.exports = { js: "never", }, ], + "no-unused-vars": ["error", { ignoreRestSiblings: true }], // allow debugger during development "no-debugger": process.env.NODE_ENV === "production" ? "error" : "off", "vue/html-indent": "off", diff --git a/src/components/Finder.vue b/src/components/Finder.vue index e7edcf8..9e2a0f9 100644 --- a/src/components/Finder.vue +++ b/src/components/Finder.vue @@ -270,7 +270,7 @@ export default { autoDeselectDescendants: this.autoDeselectDescendants, }); - this.treeModel.on("expand", (expanded, sourceEvent) => { + this.treeModel.on("expand", (expanded, sourceEvent, expandedItems) => { if (sourceEvent !== "dragover") { this.$nextTick(() => { this._scrollToRight(this.scrollAnimationDuration); @@ -285,7 +285,7 @@ export default { * ``` * * ```js - * onExpand({ expanded, sourceEvent }) { + * onExpand({ expanded, sourceEvent, expandedItems }) { * console.log( * `Items with ${expanded.join()} IDs are now expanded` * ); @@ -294,16 +294,17 @@ export default { * * @event expand * @type {object} - * @property {Array} expanded IDs of expanded items - * @property {string} sourceEvent Name of the event that triggered the action - * (`"click"`, `"focus"`, `"drop"`, `"dragover"` or `undefined`) + * @property {Array} expanded IDs of expanded items + * @property {string} sourceEvent Name of the event that triggered the action (`"click"`, `"focus"`, `"drop"`, `"dragover"` or `undefined`) + * @property {Array} expandedItems List of expanded items */ this.$emit("expand", { expanded, sourceEvent, + expandedItems, }); }); - this.treeModel.on("select", (selected) => { + this.treeModel.on("select", (selected, selectedItems) => { /** * This event is triggered when an item has been selected. * @@ -312,7 +313,7 @@ export default { * ``` * * ```js - * onSelect({ selected }) { + * onSelect({ selected, selectedItems }) { * console.log( * `Items with ${selected.join()} IDs are now selected` * ); @@ -321,10 +322,12 @@ export default { * * @event select * @type {object} - * @property {Array} selected IDs of selected items + * @property {Array} selected IDs of selected items + * @property {Array} selectedItems List of selected items */ this.$emit("select", { selected, + selectedItems, }); }); this.treeModel.on("move", ({ moved, to, index }) => { diff --git a/src/components/__tests__/Finder.test.js b/src/components/__tests__/Finder.test.js index 6e1bfa7..e75389f 100644 --- a/src/components/__tests__/Finder.test.js +++ b/src/components/__tests__/Finder.test.js @@ -132,7 +132,18 @@ describe("Finder", () => { await wrapper.findAll(".item")[0].trigger("focus"); expect(wrapper.emitted().expand).toEqual([ - [{ expanded: ["test1", "test11"], sourceEvent: "focus" }], + [ + { + expanded: ["test1", "test11"], + sourceEvent: "focus", + expandedItems: [ + { + id: "test1", + }, + { id: "test11", label: "Test 11" }, + ], + }, + ], ]); expect(wrapper.html()).toMatchSnapshot(); }); @@ -273,6 +284,33 @@ describe("Finder", () => { "test142", "test12", ], + selectedItems: [ + { + id: "test11", + label: "Test 11", + }, + { + id: "test14", + label: "Test 14", + }, + { + id: "test141", + label: "Test 141", + }, + { + id: "test1411", + label: "Test 1411", + }, + { + id: "test1412", + label: "Test 1412", + }, + { + id: "test142", + label: "Test 142", + }, + { id: "test12", label: "Test 12" }, + ], }, ], ]); @@ -306,6 +344,49 @@ describe("Finder", () => { "test132", "test13", ], + selectedItems: [ + { + id: "test11", + label: "Test 11", + }, + { + id: "test14", + label: "Test 14", + }, + { + id: "test141", + label: "Test 141", + }, + { + id: "test1411", + label: "Test 1411", + }, + { + id: "test1412", + label: "Test 1412", + }, + { + id: "test142", + label: "Test 142", + }, + { + id: "test1311", + label: "Test 1311", + }, + { + id: "test1312", + label: "Test 1312", + }, + { + id: "test131", + label: "Test 131", + }, + { + id: "test132", + label: "Test 132", + }, + { id: "test13", label: "Test 13" }, + ], }, ], ]); @@ -323,7 +404,19 @@ describe("Finder", () => { await wrapper.findAll(".item > input[type=checkbox]")[3].trigger("click"); - expect(wrapper.emitted().select).toEqual([[{ selected: ["test11"] }]]); + expect(wrapper.emitted().select).toEqual([ + [ + { + selected: ["test11"], + selectedItems: [ + { + id: "test11", + label: "Test 11", + }, + ], + }, + ], + ]); }); }); @@ -380,6 +473,20 @@ describe("Finder", () => { { expanded: ["test1", "test11", "test112"], sourceEvent: "api", + expandedItems: [ + { + id: "test1", + }, + { + id: "test11", + label: "Test 11", + }, + { + id: "test112", + label: "Test 112", + cssClass: "custom-class", + }, + ], }, ], ]); @@ -402,6 +509,20 @@ describe("Finder", () => { { expanded: ["test1", "test11", "test112"], sourceEvent: "custom-event", + expandedItems: [ + { + id: "test1", + }, + { + id: "test11", + label: "Test 11", + }, + { + id: "test112", + label: "Test 112", + cssClass: "custom-class", + }, + ], }, ], ]); diff --git a/src/utils/__tests__/tree-model.test.js b/src/utils/__tests__/tree-model.test.js index 8c8a0c5..3552448 100644 --- a/src/utils/__tests__/tree-model.test.js +++ b/src/utils/__tests__/tree-model.test.js @@ -74,7 +74,14 @@ describe("TreeModel", () => { it("should return `true` if node is selected", () => { model.expandNode("test11"); expect(model.isNodeExpanded("test11")).toBe(true); - expect(onExpand).toHaveBeenCalledWith(["test1", "test11"], undefined); + expect(onExpand).toHaveBeenCalledWith(["test1", "test11"], undefined, [ + { + id: "test1", + }, + { + id: "test11", + }, + ]); expect(model.visibleTree).toEqual({ id: "test1", children: [ @@ -124,13 +131,23 @@ describe("TreeModel", () => { describe("#selectNode", () => { it("should select node and trigger an event", () => { model.selectNode("test12", true); - expect(onSelect).toHaveBeenCalledWith(["test11", "test12"]); + expect(onSelect).toHaveBeenCalledWith( + ["test11", "test12"], + [ + { + id: "test11", + }, + { + id: "test12", + }, + ] + ); expect(model.isNodeSelected("test12")).toBe(true); }); it("should unselect a node and trigger an event", () => { model.selectNode("test11", false); - expect(onSelect).toHaveBeenCalledWith([]); + expect(onSelect).toHaveBeenCalledWith([], []); expect(model.isNodeSelected("test11")).toBe(false); }); }); @@ -391,7 +408,13 @@ describe("TreeModel", () => { }); expect(onExpand).toHaveBeenCalledWith( ["test1", "test11", "test112", "test12"], - "drop" + "drop", + [ + { id: "test1" }, + { id: "test11" }, + { id: "test112" }, + { id: "test12" }, + ] ); expect(onMove).toHaveBeenCalledWith({ moved: "test12", @@ -437,7 +460,8 @@ describe("TreeModel", () => { }); expect(onExpand).toHaveBeenCalledWith( ["test1", "test11", "test12"], - "drop" + "drop", + [{ id: "test1" }, { id: "test11" }, { id: "test12" }] ); expect(onMove).toHaveBeenCalledWith({ moved: "test12", diff --git a/src/utils/tree-model.js b/src/utils/tree-model.js index 47bec93..9a07b54 100644 --- a/src/utils/tree-model.js +++ b/src/utils/tree-model.js @@ -113,6 +113,11 @@ export default class extends EventManager { return this.nodesMap[nodeId]; } + _getNodeData(nodeId) { + const { children, parent, selected, ...data } = this.nodesMap[nodeId]; + return data; + } + /** * Expand a node. * @@ -123,7 +128,12 @@ export default class extends EventManager { this.expanded = path(nodeId, this.nodesMap); this.expandedWithoutFilter = this.expanded; this._updateVisibleTree(); - this.trigger("expand", this.expanded, sourceEvent); + this.trigger( + "expand", + this.expanded, + sourceEvent, + this.expanded.map((id) => this._getNodeData(id)) + ); } isNodeExpanded(nodeId) { @@ -145,7 +155,11 @@ export default class extends EventManager { this.selected, nodeIdsToSelect ); - this.trigger("select", this.selected); + this.trigger( + "select", + this.selected, + this.selected.map((id) => this._getNodeData(id)) + ); } isNodeSelected(nodeId) { diff --git a/stories/index.stories.js b/stories/index.stories.js index 0692d85..8355cb4 100644 --- a/stories/index.stories.js +++ b/stories/index.stories.js @@ -95,6 +95,9 @@ export default { component: Finder, argTypes: { filter: { control: "text" }, + onExpand: { action: "expand" }, + onMove: { action: "move" }, + onSelect: { action: "select" }, }, };