@react-md/tree
Advanced tools
+12
-0
@@ -6,2 +6,14 @@ # Change Log | ||
| ## [2.9.1](https://github.com/mlaursen/react-md/compare/v2.9.0...v2.9.1) (2021-07-27) | ||
| ### Other Internal Changes | ||
| * **install:** slighly reduce install size by excluding tests in publish ([9d01a44](https://github.com/mlaursen/react-md/commit/9d01a44b81b619d6ac1c4d458005c99838fc6894)) | ||
| # [2.9.0](https://github.com/mlaursen/react-md/compare/v2.8.5...v2.9.0) (2021-07-18) | ||
@@ -8,0 +20,0 @@ |
+7
-14
| { | ||
| "name": "@react-md/tree", | ||
| "version": "2.9.0", | ||
| "version": "2.9.1", | ||
| "description": "A package for creating an accessible tree component following the tree role.", | ||
@@ -11,9 +11,2 @@ "main": "./lib/index.js", | ||
| ], | ||
| "files": [ | ||
| "es/*", | ||
| "lib/*", | ||
| "types/*", | ||
| "src/*", | ||
| "dist/*" | ||
| ], | ||
| "author": "Mikkel Laursen <mlaursen03@gmail.com>", | ||
@@ -40,7 +33,7 @@ "repository": { | ||
| "dependencies": { | ||
| "@react-md/icon": "^2.9.0", | ||
| "@react-md/list": "^2.9.0", | ||
| "@react-md/theme": "^2.9.0", | ||
| "@react-md/transition": "^2.9.0", | ||
| "@react-md/utils": "^2.9.0", | ||
| "@react-md/icon": "^2.9.1", | ||
| "@react-md/list": "^2.9.1", | ||
| "@react-md/theme": "^2.9.1", | ||
| "@react-md/transition": "^2.9.1", | ||
| "@react-md/utils": "^2.9.1", | ||
| "classnames": "^2.3.1" | ||
@@ -61,3 +54,3 @@ }, | ||
| }, | ||
| "gitHead": "4d2ab41e4f72827ce7c3337c6cc2506533fc199f" | ||
| "gitHead": "9a1f1f2c7bb8d7c88a200d134d123ef3f5ecf208" | ||
| } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
| import { getChildItems } from "../getChildItems"; | ||
| const item1 = { | ||
| itemId: "item-id-1", | ||
| name: "item", | ||
| parentId: "root", | ||
| }; | ||
| const item2 = { | ||
| itemId: "item-id-2", | ||
| name: "item", | ||
| parentId: "item-id-3", | ||
| }; | ||
| const item3 = { | ||
| itemId: "item-id-3", | ||
| name: "item", | ||
| parentId: "root", | ||
| }; | ||
| const item4 = { | ||
| itemId: "item-id-4", | ||
| name: "item", | ||
| parentId: "item-id-3", | ||
| }; | ||
| const item5 = { | ||
| itemId: "item-id-5", | ||
| name: "item", | ||
| parentId: "item-id-4", | ||
| }; | ||
| const data = { | ||
| "item-id-1": item1, | ||
| "item-id-2": item2, | ||
| "item-id-3": item3, | ||
| "item-id-4": item4, | ||
| "item-id-5": item5, | ||
| }; | ||
| describe("getChildItems", () => { | ||
| it("should return an empty list if there are not items with the provided parentId", () => { | ||
| expect(getChildItems({}, null)).toEqual([]); | ||
| expect(getChildItems({}, "")).toEqual([]); | ||
| expect(getChildItems({}, "noop")).toEqual([]); | ||
| expect(getChildItems(data, "noop")).toEqual([]); | ||
| expect(getChildItems(data, "item-id")).toEqual([]); | ||
| }); | ||
| it("should return a list of all the items that have the matching parentId", () => { | ||
| expect(getChildItems(data, "root", false)).toEqual([item1, item3]); | ||
| expect(getChildItems(data, "item-id-3", false)).toEqual([item2, item4]); | ||
| expect(getChildItems(data, "item-id-4", false)).toEqual([item5]); | ||
| }); | ||
| it("should return a list of all the items that have the matching parentId(s)", () => { | ||
| expect(getChildItems(data, "item-id-3", true)).toEqual([ | ||
| item2, | ||
| item4, | ||
| item5, | ||
| ]); | ||
| expect(getChildItems(data, "item-id-4", true)).toEqual([item5]); | ||
| // just to show the traversal order even though it doesn't really matter much | ||
| expect(getChildItems(data, "root", true)).toEqual([ | ||
| item1, | ||
| item3, | ||
| item2, | ||
| item4, | ||
| item5, | ||
| ]); | ||
| }); | ||
| it("should default to not recursively matching items", () => { | ||
| expect(getChildItems(data, "root")).toEqual([item1, item3]); | ||
| expect(getChildItems(data, "item-id-3")).toEqual([item2, item4]); | ||
| expect(getChildItems(data, "item-id-4")).toEqual([item5]); | ||
| }); | ||
| }); |
| import { getItemsFrom } from "../getItemsFrom"; | ||
| const item1 = { | ||
| itemId: "item-id-1", | ||
| name: "item", | ||
| parentId: null, | ||
| }; | ||
| const item2 = { | ||
| itemId: "item-id-2", | ||
| name: "item", | ||
| parentId: "item-id-3", | ||
| }; | ||
| const item3 = { | ||
| itemId: "item-id-3", | ||
| name: "item", | ||
| parentId: null, | ||
| }; | ||
| const item4 = { | ||
| itemId: "item-id-4", | ||
| name: "item", | ||
| parentId: "item-id-3", | ||
| }; | ||
| const item5 = { | ||
| itemId: "item-id-5", | ||
| name: "item", | ||
| parentId: "item-id-4", | ||
| }; | ||
| const data = { | ||
| "item-id-1": item1, | ||
| "item-id-2": item2, | ||
| "item-id-3": item3, | ||
| "item-id-4": item4, | ||
| "item-id-5": item5, | ||
| }; | ||
| describe("getItemsFrom", () => { | ||
| it("should return an empty list if the provided itemId does not exist in the data or is null", () => { | ||
| expect(getItemsFrom(data, "item-100000")).toEqual([]); | ||
| expect(getItemsFrom(data, null)).toEqual([]); | ||
| }); | ||
| it("should return the corrected oredred list of items", () => { | ||
| expect(getItemsFrom(data, "item-id-1")).toEqual([item1]); | ||
| expect(getItemsFrom(data, "item-id-3")).toEqual([item3]); | ||
| expect(getItemsFrom(data, "item-id-4")).toEqual([item4, item3]); | ||
| expect(getItemsFrom(data, "item-id-2")).toEqual([item2, item3]); | ||
| expect(getItemsFrom(data, "item-id-5")).toEqual([item5, item4, item3]); | ||
| }); | ||
| }); |
| import { getTreeItemId } from "../getTreeItemId"; | ||
| describe("getTreeItemId", () => { | ||
| it("should return the correct id when the parentIndexes are omitted or an empty list", () => { | ||
| expect(getTreeItemId("tree-id", 0)).toBe("tree-id-item-1"); | ||
| expect(getTreeItemId("tree-id", 2)).toBe("tree-id-item-3"); | ||
| expect(getTreeItemId("tree-id", 10)).toBe("tree-id-item-11"); | ||
| expect(getTreeItemId("tree-id", 0, [])).toBe("tree-id-item-1"); | ||
| expect(getTreeItemId("tree-id", 2, [])).toBe("tree-id-item-3"); | ||
| expect(getTreeItemId("tree-id", 10, [])).toBe("tree-id-item-11"); | ||
| }); | ||
| it("should return the correct id for all the provided parentIndexes", () => { | ||
| expect(getTreeItemId("tree-id", 0, [1])).toBe("tree-id-item-1-1"); | ||
| expect(getTreeItemId("tree-id", 0, [3])).toBe("tree-id-item-3-1"); | ||
| expect(getTreeItemId("tree-id", 0, [1, 1, 1])).toBe("tree-id-item-1-1-1-1"); | ||
| expect(getTreeItemId("tree-id", 0, [3, 2, 5, 1, 2])).toBe( | ||
| "tree-id-item-3-2-5-1-2-1" | ||
| ); | ||
| }); | ||
| }); |
| import React from "react"; | ||
| import { render } from "@testing-library/react"; | ||
| import { Tree } from "../Tree"; | ||
| const PROPS = { | ||
| id: "tree", | ||
| data: {}, | ||
| expandedIds: [], | ||
| onItemExpansion: () => {}, | ||
| onMultiItemExpansion: () => {}, | ||
| selectedIds: [], | ||
| onItemSelect: () => {}, | ||
| onMultiItemSelect: () => {}, | ||
| }; | ||
| describe("Tree", () => { | ||
| it("should be able to render an empty tree", () => { | ||
| const { container } = render(<Tree {...PROPS} />); | ||
| expect(container).toMatchSnapshot(); | ||
| }); | ||
| it("should be able to render a tree with muliple root level nodes", () => { | ||
| const data = { | ||
| "item-1": { | ||
| parentId: null, | ||
| itemId: "item-1", | ||
| name: "Item 1", | ||
| }, | ||
| "item-3": { | ||
| parentId: null, | ||
| itemId: "item-3", | ||
| name: "Item 3", | ||
| }, | ||
| "item-2": { | ||
| parentId: null, | ||
| itemId: "item-2", | ||
| name: "Item 2", | ||
| }, | ||
| }; | ||
| const { container } = render(<Tree {...PROPS} data={data} />); | ||
| expect(container).toMatchSnapshot(); | ||
| }); | ||
| it("should be able to use a rootId that is not null", () => { | ||
| const data = { | ||
| "item-1": { | ||
| parentId: "root-id", | ||
| itemId: "item-1", | ||
| name: "Item 1", | ||
| }, | ||
| "item-3": { | ||
| parentId: "root-id", | ||
| itemId: "item-3", | ||
| name: "Item 3", | ||
| }, | ||
| "item-2": { | ||
| parentId: "root-id", | ||
| itemId: "item-2", | ||
| name: "Item 2", | ||
| }, | ||
| }; | ||
| const { container, getByRole } = render( | ||
| <Tree {...PROPS} data={data} rootId="root-id" /> | ||
| ); | ||
| expect(container).toMatchSnapshot(); | ||
| const tree = getByRole("tree"); | ||
| expect(tree.firstElementChild).not.toBeNull(); | ||
| }); | ||
| it("should pass the tree item's className and liClassName attributes by default", () => { | ||
| const data = { | ||
| "item-1": { | ||
| parentId: null, | ||
| itemId: "item-1", | ||
| name: "Item 1", | ||
| className: "item-1-class-name", | ||
| liClassName: "item-1-li-class-name", | ||
| }, | ||
| }; | ||
| const { container, getByRole } = render(<Tree {...PROPS} data={data} />); | ||
| expect(container).toMatchSnapshot(); | ||
| const item = getByRole("treeitem"); | ||
| expect(item.className).toContain("item-1-li-class-name"); | ||
| expect(item.children[0].className).toContain("item-1-class-name"); | ||
| }); | ||
| }); |
| import React from "react"; | ||
| import { render } from "@testing-library/react"; | ||
| import { TreeGroup } from "../TreeGroup"; | ||
| describe("TreeGroup", () => { | ||
| it("should render correctly", () => { | ||
| const props = { | ||
| collapsed: true, | ||
| children: ( | ||
| <> | ||
| <li>Item 1</li> | ||
| </> | ||
| ), | ||
| }; | ||
| const { container, rerender } = render(<TreeGroup {...props} />); | ||
| expect(container).toMatchSnapshot(); | ||
| rerender(<TreeGroup {...props} collapsed={false} />); | ||
| expect(container).toMatchSnapshot(); | ||
| }); | ||
| }); |
| import React from "react"; | ||
| import { render } from "@testing-library/react"; | ||
| import { TreeItemExpanderIcon } from "../TreeItemExpanderIcon"; | ||
| describe("TreeItemExpanderIcon", () => { | ||
| it("should render correctly", () => { | ||
| const { container, rerender } = render( | ||
| <TreeItemExpanderIcon rotated={false}> | ||
| <i>icon</i> | ||
| </TreeItemExpanderIcon> | ||
| ); | ||
| expect(container).toMatchSnapshot(); | ||
| rerender( | ||
| <TreeItemExpanderIcon rotated> | ||
| <i>icon</i> | ||
| </TreeItemExpanderIcon> | ||
| ); | ||
| expect(container).toMatchSnapshot(); | ||
| }); | ||
| }); |
| import { BaseTreeItem, TreeData } from "../types"; | ||
| import { buildTree } from "../useNestedTreeList"; | ||
| interface TestTreeItem extends BaseTreeItem { | ||
| children: string; | ||
| } | ||
| const TREE: TreeData<TestTreeItem> = { | ||
| "item-1": { | ||
| itemId: "item-1", | ||
| parentId: null, | ||
| children: "Content 1", | ||
| }, | ||
| "item-2": { | ||
| itemId: "item-2", | ||
| parentId: null, | ||
| children: "Content 2", | ||
| }, | ||
| "item-3": { | ||
| itemId: "item-3", | ||
| parentId: null, | ||
| children: "Content 3", | ||
| }, | ||
| "item-4": { | ||
| itemId: "item-4", | ||
| parentId: null, | ||
| children: "Content 4", | ||
| }, | ||
| "item-5": { | ||
| itemId: "item-5", | ||
| parentId: null, | ||
| children: "Content 5", | ||
| }, | ||
| }; | ||
| const NESTED_TREE: TreeData<TestTreeItem> = { | ||
| "item-1": { | ||
| itemId: "item-1", | ||
| parentId: null, | ||
| children: "Content 1", | ||
| }, | ||
| "item-1-1": { | ||
| itemId: "item-1-1", | ||
| parentId: "item-1", | ||
| children: "Content 1-1", | ||
| }, | ||
| "item-1-1-1": { | ||
| itemId: "item-1-1-1", | ||
| parentId: "item-1-1", | ||
| children: "Content 1-1-1", | ||
| }, | ||
| "item-2": { | ||
| itemId: "item-2", | ||
| parentId: null, | ||
| children: "Content 2", | ||
| }, | ||
| "item-2-1": { | ||
| itemId: "item-2-1", | ||
| parentId: "item-2", | ||
| children: "Content 2-1", | ||
| }, | ||
| "item-2-2": { | ||
| itemId: "item-2-2", | ||
| parentId: "item-2", | ||
| children: "Content 2-2", | ||
| }, | ||
| }; | ||
| describe("buildTree", () => { | ||
| it("should return undefined if the tree is empty", () => { | ||
| const data: TreeData<TestTreeItem> = {}; | ||
| expect(buildTree(null, Object.values(data))).toBeUndefined(); | ||
| }); | ||
| it("should be able to create a tree with a single item", () => { | ||
| const data: TreeData<TestTreeItem> = { | ||
| "item-1": { | ||
| itemId: "item-1", | ||
| parentId: null, | ||
| children: "Content", | ||
| }, | ||
| }; | ||
| expect(buildTree(null, Object.values(data))).toEqual([ | ||
| { itemId: "item-1", children: "Content", parentId: null }, | ||
| ]); | ||
| }); | ||
| it("should be able to create a tree with multiple items on the root level", () => { | ||
| const expected = [ | ||
| { itemId: "item-1", children: "Content 1", parentId: null }, | ||
| { itemId: "item-2", children: "Content 2", parentId: null }, | ||
| { itemId: "item-3", children: "Content 3", parentId: null }, | ||
| { itemId: "item-4", children: "Content 4", parentId: null }, | ||
| { itemId: "item-5", children: "Content 5", parentId: null }, | ||
| ]; | ||
| expect(buildTree(null, Object.values(TREE))).toEqual(expected); | ||
| }); | ||
| it("should be able to create a tree with multiple levels", () => { | ||
| const expected = [ | ||
| { | ||
| itemId: "item-1", | ||
| parentId: null, | ||
| children: "Content 1", | ||
| childItems: [ | ||
| { | ||
| itemId: "item-1-1", | ||
| parentId: "item-1", | ||
| children: "Content 1-1", | ||
| childItems: [ | ||
| { | ||
| itemId: "item-1-1-1", | ||
| parentId: "item-1-1", | ||
| children: "Content 1-1-1", | ||
| }, | ||
| ], | ||
| }, | ||
| ], | ||
| }, | ||
| { | ||
| itemId: "item-2", | ||
| parentId: null, | ||
| children: "Content 2", | ||
| childItems: [ | ||
| { | ||
| itemId: "item-2-1", | ||
| parentId: "item-2", | ||
| children: "Content 2-1", | ||
| }, | ||
| { | ||
| itemId: "item-2-2", | ||
| parentId: "item-2", | ||
| children: "Content 2-2", | ||
| }, | ||
| ], | ||
| }, | ||
| ]; | ||
| expect(buildTree(null, Object.values(NESTED_TREE))).toEqual(expected); | ||
| }); | ||
| }); |
| import { act, renderHook } from "@testing-library/react-hooks"; | ||
| import { useTreeItemExpansion } from "../useTreeItemExpansion"; | ||
| describe("useTreeItemExpansion", () => { | ||
| it("should set the initial expandedIds to the provided default ids", () => { | ||
| let { result } = renderHook(() => useTreeItemExpansion([])); | ||
| expect(result.current.expandedIds).toEqual([]); | ||
| const expandedIds = ["id-1", "id-3", "id-4"]; | ||
| ({ result } = renderHook(() => useTreeItemExpansion(expandedIds))); | ||
| expect(result.current.expandedIds).toEqual(expandedIds); | ||
| }); | ||
| it("should add itemIds correctly when the onItemExpansion is called", () => { | ||
| const { result } = renderHook(() => useTreeItemExpansion([])); | ||
| const { onItemExpansion } = result.current; | ||
| let { expandedIds } = result.current; | ||
| expect(expandedIds).toEqual([]); | ||
| act(() => { | ||
| onItemExpansion("id-1", true); | ||
| }); | ||
| ({ expandedIds } = result.current); | ||
| expect(expandedIds).toEqual(["id-1"]); | ||
| act(() => { | ||
| onItemExpansion("id-1", true); | ||
| onItemExpansion("id-1", true); | ||
| onItemExpansion("id-1", true); | ||
| }); | ||
| // it should not have updated | ||
| expect(result.current.expandedIds).toBe(expandedIds); | ||
| act(() => { | ||
| onItemExpansion("id-2", true); | ||
| }); | ||
| expect(result.current.expandedIds).not.toBe(expandedIds); | ||
| ({ expandedIds } = result.current); | ||
| expect(expandedIds).toEqual(["id-1", "id-2"]); | ||
| }); | ||
| it("should remove itemIds correctly when the onItemExpansion is called", () => { | ||
| const defaultExpandedIds = ["id-1", "id-2", "id-3"]; | ||
| const { result } = renderHook(() => | ||
| useTreeItemExpansion(defaultExpandedIds) | ||
| ); | ||
| const { onItemExpansion } = result.current; | ||
| let { expandedIds } = result.current; | ||
| expect(expandedIds).toEqual(defaultExpandedIds); | ||
| act(() => { | ||
| onItemExpansion("id-100", false); | ||
| }); | ||
| // it should not have updated | ||
| expect(result.current.expandedIds).toBe(expandedIds); | ||
| act(() => { | ||
| onItemExpansion("id-1", false); | ||
| }); | ||
| ({ expandedIds } = result.current); | ||
| expect(expandedIds).toEqual(["id-2", "id-3"]); | ||
| act(() => { | ||
| onItemExpansion("id-3", false); | ||
| }); | ||
| ({ expandedIds } = result.current); | ||
| expect(expandedIds).toEqual(["id-2"]); | ||
| act(() => { | ||
| onItemExpansion("id-2", false); | ||
| }); | ||
| ({ expandedIds } = result.current); | ||
| expect(expandedIds).toEqual([]); | ||
| }); | ||
| it("should always update the expandedIds to the provided itemIds when the onMultiItemExpansion is called", () => { | ||
| const ids1 = ["id-1"]; | ||
| const ids2 = ["id-2", "id-1", "id-3"]; | ||
| const { result } = renderHook(() => useTreeItemExpansion([])); | ||
| const { onMultiItemExpansion } = result.current; | ||
| expect(result.current.expandedIds).toEqual([]); | ||
| act(() => { | ||
| onMultiItemExpansion(ids1); | ||
| }); | ||
| expect(result.current.expandedIds).toEqual(ids1); | ||
| act(() => { | ||
| onMultiItemExpansion(ids2); | ||
| }); | ||
| expect(result.current.expandedIds).toEqual(ids2); | ||
| }); | ||
| }); |
| import { act, renderHook } from "@testing-library/react-hooks"; | ||
| import { useTreeItemSelection } from "../useTreeItemSelection"; | ||
| describe("useTreeItemSelection", () => { | ||
| it("should default to the provided selectedIds list", () => { | ||
| let { result } = renderHook(() => useTreeItemSelection([], false)); | ||
| expect(result.current.selectedIds).toEqual([]); | ||
| ({ result } = renderHook(() => useTreeItemSelection([], true))); | ||
| expect(result.current.selectedIds).toEqual([]); | ||
| const defaultIds = ["id-1", "id-2"]; | ||
| ({ result } = renderHook(() => useTreeItemSelection(defaultIds, false))); | ||
| expect(result.current.selectedIds).toEqual(defaultIds); | ||
| ({ result } = renderHook(() => useTreeItemSelection(defaultIds, true))); | ||
| expect(result.current.selectedIds).toEqual(defaultIds); | ||
| }); | ||
| it("should handle updating the selectedIds list for single select behavior", () => { | ||
| const { result } = renderHook(() => useTreeItemSelection([], false)); | ||
| const { onItemSelect } = result.current; | ||
| let { selectedIds } = result.current; | ||
| expect(selectedIds).toEqual([]); | ||
| act(() => { | ||
| onItemSelect("id-1"); | ||
| }); | ||
| ({ selectedIds } = result.current); | ||
| expect(selectedIds).toEqual(["id-1"]); | ||
| act(() => { | ||
| onItemSelect("id-1"); | ||
| }); | ||
| // it should not have updated | ||
| expect(result.current.selectedIds).toBe(selectedIds); | ||
| act(() => { | ||
| onItemSelect("id-2"); | ||
| }); | ||
| expect(result.current.selectedIds).not.toBe(selectedIds); | ||
| ({ selectedIds } = result.current); | ||
| expect(selectedIds).toEqual(["id-2"]); | ||
| }); | ||
| it("should handle updating the selected ids for multi-select behavior", () => { | ||
| const { result } = renderHook(() => useTreeItemSelection([], true)); | ||
| const { onItemSelect } = result.current; | ||
| let { selectedIds } = result.current; | ||
| expect(selectedIds).toEqual([]); | ||
| act(() => { | ||
| onItemSelect("id-1"); | ||
| }); | ||
| ({ selectedIds } = result.current); | ||
| expect(selectedIds).toEqual(["id-1"]); | ||
| act(() => { | ||
| onItemSelect("id-1"); | ||
| }); | ||
| ({ selectedIds } = result.current); | ||
| expect(selectedIds).toEqual([]); | ||
| act(() => { | ||
| onItemSelect("id-1"); | ||
| onItemSelect("id-2"); | ||
| }); | ||
| ({ selectedIds } = result.current); | ||
| expect(selectedIds).toEqual(["id-1", "id-2"]); | ||
| }); | ||
| it("should default to single select behavior", () => { | ||
| // same tests as the single select test | ||
| const { result } = renderHook(() => useTreeItemSelection([])); | ||
| const { onItemSelect } = result.current; | ||
| let { selectedIds } = result.current; | ||
| expect(selectedIds).toEqual([]); | ||
| act(() => { | ||
| onItemSelect("id-1"); | ||
| }); | ||
| ({ selectedIds } = result.current); | ||
| expect(selectedIds).toEqual(["id-1"]); | ||
| act(() => { | ||
| onItemSelect("id-1"); | ||
| }); | ||
| // it should not have updated | ||
| expect(result.current.selectedIds).toBe(selectedIds); | ||
| act(() => { | ||
| onItemSelect("id-2"); | ||
| }); | ||
| expect(result.current.selectedIds).not.toBe(selectedIds); | ||
| ({ selectedIds } = result.current); | ||
| expect(selectedIds).toEqual(["id-2"]); | ||
| }); | ||
| }); |
| //// | ||
| /// @group tree | ||
| //// | ||
| @import '~@react-md/theme/dist/helpers'; | ||
| @import './variables'; | ||
| /// This function is used to quickly get one of the tree's theme values. This is | ||
| /// really just for the `rmd-tree-theme` mixin to provide some validation that a | ||
| /// correct style key is used, but might be useful in other cases. | ||
| /// | ||
| /// @param {String} theme-style - One of the `$rmd-tree-theme-values` map keys | ||
| /// to get a value for. | ||
| /// @return {Color|String|Number} one of the tree's theme values. | ||
| @function rmd-tree-theme($theme-style) { | ||
| @return rmd-theme-get-var-value($theme-style, $rmd-tree-theme-values, tree); | ||
| } | ||
| /// This function is used to get one of the tree's theme variables as a CSS | ||
| /// Variable to be applied as a style attribute. By default, the CSS Variable | ||
| /// will have a fallback of the current `$rmd-tree-theme-values` | ||
| /// | ||
| /// This function is used to create a CSS Variable declaration with an optional | ||
| /// fallback value if the CSS Variable has not been declared somehow. | ||
| /// | ||
| /// @param {String} theme-style - One of the `$rmd-tree-theme-values` map keys | ||
| /// to set a value for. | ||
| /// @param {Color|String|Number} fallback [null] - An optional fallback color to | ||
| /// apply. This is set to `null` by default and not used since the link's theme | ||
| /// variables should always exist. | ||
| /// @return {String} one of the tree's theme values as a css variable. | ||
| @function rmd-tree-theme-var($theme-style, $fallback: null) { | ||
| @return rmd-theme-get-var( | ||
| $theme-style, | ||
| $rmd-tree-theme-values, | ||
| tree, | ||
| $fallback | ||
| ); | ||
| } |
-209
| //// | ||
| /// @group tree | ||
| //// | ||
| @import '~@react-md/icon/dist/mixins'; | ||
| @import '~@react-md/list/dist/mixins'; | ||
| @import '~@react-md/theme/dist/helpers'; | ||
| @import '~@react-md/utils/dist/mixins'; | ||
| @import './variables'; | ||
| @import './functions'; | ||
| /// Creates the styles for one of the tree's theme values. This is mostly going | ||
| /// to be an internal helper mixin util. | ||
| /// | ||
| /// @param {String} property - The property to set a `rmd-tree-theme-values` | ||
| /// value to. | ||
| /// @param {String} theme-style - One of the keys of `rmd-tree-theme-values` to | ||
| /// extract a value from. | ||
| /// @param {Color|String|Number} fallback [null] - A fallback value to use if | ||
| /// the css variable isn't set somehow. This will default to automatically | ||
| /// retrieving the default value from the `rmd-tree-theme-values` map when | ||
| /// `null`. | ||
| @mixin rmd-tree-theme($property, $theme-style: $property, $fallback: null) { | ||
| @include rmd-theme-apply-rmd-var( | ||
| $property, | ||
| $theme-style, | ||
| $rmd-tree-theme-values, | ||
| tree | ||
| ); | ||
| } | ||
| /// Updates one of the tree's theme variables with the new value for the section | ||
| /// of your app. | ||
| /// | ||
| /// @param {String} theme-style - The tree theme style type to update. This | ||
| /// should be one of the `$rmd-tree-theme-values` keys. | ||
| /// @param {Color|String|Number} value - The new value to use. | ||
| @mixin rmd-tree-theme-update-var($theme-style, $value) { | ||
| @include rmd-theme-update-rmd-var( | ||
| $value, | ||
| $theme-style, | ||
| $rmd-tree-theme-values, | ||
| tree | ||
| ); | ||
| } | ||
| /// Creates the styles for all the depths from the provided min and max values | ||
| /// for a tree. | ||
| /// | ||
| /// @example scss - Simple Usage | ||
| /// .tree { | ||
| /// @include rmd-tree-depths($max: 2, $base-padding: 2rem); | ||
| /// } | ||
| /// | ||
| /// @example scss - CSS Modules Usage | ||
| /// .tree { | ||
| /// @include rmd-tree-depths($selector-prefix: ':global ', $max: 2, $base-padding: 2rem); | ||
| /// } | ||
| /// | ||
| /// @param {String} selector-prefix [''] - An optional prefix to apply before | ||
| /// the `aria-level` selector. This should be set to `':global '` when using CSS | ||
| /// Modules since it relies on global `.rmd-tree-item__content` class names. | ||
| /// @param {Number} min [1] - The min level to use. This needs to be a number | ||
| /// greater than 0. | ||
| /// @param {Number} max [$rmd-tree-max-depth] - The max number of levels to | ||
| /// create styles for. | ||
| /// @param {Number} incrementor [$rmd-tree-item-padding-incrementor] - The amount | ||
| /// of padding to be used for each level of depth. | ||
| /// @param {Number} base [$rmd-tree-item-padding-base] - The base amount of | ||
| /// padding that should be added to a tree item. | ||
| @mixin rmd-tree-depths( | ||
| $selector-prefix: '', | ||
| $min: 1, | ||
| $max: $rmd-tree-max-depth, | ||
| $incrementor: $rmd-tree-item-padding-incrementor, | ||
| $base-padding: $rmd-tree-item-padding-base | ||
| ) { | ||
| @if $min < 1 { | ||
| @error 'Invalid min value: \'#{$min}\'! The min must be a number greater than 0.'; | ||
| } | ||
| @if $max < $min { | ||
| @error 'Invalid max value: \'#{$max}\'! The max must be a number greater than the min value: \'#{$min}\''; | ||
| } | ||
| $index: $min; | ||
| @while $index < $max { | ||
| @include rmd-tree-item-at-depth( | ||
| $index, | ||
| $selector-prefix, | ||
| $incrementor, | ||
| $base-padding | ||
| ); | ||
| $index: $index + 1; | ||
| } | ||
| } | ||
| /// Creates styles to add additional padding to tree items based on depth. This | ||
| /// will only work if you correctly apply the `aria-level` attributes to the | ||
| /// list items. | ||
| /// | ||
| /// The formula used for creating padding is: | ||
| /// ```scss | ||
| /// $padding: (($depth - 1) * $incrementor) + $base; | ||
| /// ``` | ||
| /// | ||
| /// @param {Number} depth - The depth to create styles for. | ||
| /// @param {String} selector-prefix [''] - An optional prefix to apply before | ||
| /// the `aria-level` selector. This should be set to `':global '` when using CSS | ||
| /// Modules since it relies on global `.rmd-tree-item__content` class names. | ||
| /// @param {Number} incrementor [$rmd-tree-item-padding-incrementor] - The amount | ||
| /// of padding to be used for each level of depth. | ||
| /// @param {Number} base [$rmd-tree-item-padding-base] - The base amount of | ||
| /// padding that should be added to a tree item. | ||
| @mixin rmd-tree-item-at-depth( | ||
| $depth, | ||
| $selector-prefix: '', | ||
| $incrementor: $rmd-tree-item-padding-incrementor, | ||
| $base: $rmd-tree-item-padding-base | ||
| ) { | ||
| $selector: '#{$selector-prefix}[aria-level="#{$depth + 1}"].rmd-tree-item__content, #{$selector-prefix}[aria-level="#{$depth + 1}"] > .rmd-tree-item__content'; | ||
| $padding: (($depth - 1) * $incrementor) + $base; | ||
| #{$selector} { | ||
| @include rmd-utils-rtl-auto( | ||
| padding-left, | ||
| $padding, | ||
| $rmd-list-item-horizontal-padding | ||
| ); | ||
| } | ||
| } | ||
| /// Creates all the styles for a tree. | ||
| @mixin rmd-tree { | ||
| @include rmd-tree-depths; | ||
| @include rmd-utils-hide-focus-outline; | ||
| @include rmd-utils-scroll; | ||
| height: 100%; | ||
| width: 100%; | ||
| } | ||
| /// Creates the styles for a tree item. This really requires the | ||
| /// `@react-md/list` styles to be created beforehand since these styles just | ||
| /// prevent the outline when focused to work with the `@react-md/states` | ||
| /// package. | ||
| /// | ||
| /// @example scss - Example Usage SCSS | ||
| /// .rmd-tree-item { | ||
| /// @include rmd-tree-item; | ||
| /// } | ||
| @mixin rmd-tree-item { | ||
| @include rmd-utils-hide-focus-outline; | ||
| // added again just-in-case so that dnd libraries don't do a bad drag image | ||
| list-style: none; | ||
| &__content { | ||
| @include rmd-list-item; | ||
| @include rmd-states-surface-selected; | ||
| &--focused { | ||
| @include rmd-utils-map-to-styles($rmd-tree-item-focused-styles); | ||
| @include rmd-utils-keyboard-only { | ||
| @include rmd-utils-map-to-styles( | ||
| $rmd-tree-item-keyboard-focused-styles | ||
| ); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| /// Creates the styles for the tree group. | ||
| /// | ||
| /// @example scss - Example Usage SCSS | ||
| /// .rmd-tree-group { | ||
| /// @include rmd-tree-group; | ||
| /// } | ||
| @mixin rmd-tree-group { | ||
| background-color: inherit; | ||
| color: inherit; | ||
| font-size: inherit; | ||
| line-height: inherit; | ||
| // remove the list padding to make it more condensed | ||
| padding-bottom: 0; | ||
| padding-top: 0; | ||
| } | ||
| /// Creates all the styles for a tree | ||
| @mixin react-md-tree { | ||
| @include rmd-theme-create-root-theme($rmd-tree-theme-values, tree); | ||
| .rmd-tree { | ||
| @include rmd-tree; | ||
| } | ||
| .rmd-tree-item { | ||
| @include rmd-tree-item; | ||
| } | ||
| .rmd-tree-group { | ||
| @include rmd-tree-group; | ||
| } | ||
| .rmd-tree-item__rotator-icon { | ||
| @include rmd-icon-theme-update-var(rotate-to, rotate(90deg)); | ||
| } | ||
| } |
| //// | ||
| /// @group tree | ||
| //// | ||
| @import '~@react-md/list/dist/variables'; | ||
| /// The default max-depth to create for the tree depths. This is used in the | ||
| /// `rmd-tree-depths` mixin to generate offsets in css based on how deep a tree | ||
| /// item is. If this value is less than or equal to 1, no depth styles will be | ||
| /// created. | ||
| /// | ||
| /// @type Number | ||
| $rmd-tree-max-depth: 3 !default; | ||
| /// The amount of padding that should be multiplied by the current depth and | ||
| /// added to the `rmd-tree-item-padding-base`. | ||
| /// | ||
| /// @see rmd-tree-depths | ||
| /// @see rmd-tree-item-at-depth | ||
| /// @require $rmd-list-item-horizontal-padding | ||
| /// @type Number | ||
| $rmd-tree-item-padding-incrementor: $rmd-list-item-horizontal-padding * 1.5 !default; | ||
| /// The base amout of padding to apply to a tree item that has a depth greater | ||
| /// than 1. This is set to a value that assumes you have icons to the left of | ||
| /// the items at the base level. If you do not, it would be better to set this | ||
| /// value to something smaller or `$rmd-list-item-horizontal-padding * 2.5`. | ||
| /// | ||
| /// @see rmd-tree-depths | ||
| /// @see rmd-tree-item-at-depth | ||
| /// @require $rmd-list-item-text-keyline | ||
| /// @type Number | ||
| $rmd-tree-item-padding-base: $rmd-list-item-text-keyline !default; | ||
| /// The styles to apply when a tree item gains focus. These styles will be | ||
| /// applied even after a touch or mouse click. | ||
| /// @type Map | ||
| $rmd-tree-item-focused-styles: () !default; | ||
| /// The styles to apply to a tree item that is **focused while in keyboard | ||
| /// mode** only. If you want to apply focus styles for all modes, use the | ||
| /// `$rmd-tree-item-focused-styles` instead and set this value to `null` or an | ||
| /// empty Map `()`. | ||
| /// | ||
| /// @see rmd-tree-item-focused-styles | ||
| /// @require $rmd-blue-500 | ||
| /// @type Map | ||
| $rmd-tree-item-keyboard-focused-styles: ( | ||
| box-shadow: inset 0 0 0 2px $rmd-blue-500, | ||
| ) !default; | ||
| /// A Map of all the "themeable" parts of the tree package. Every key in this | ||
| /// map will be used to create a css variable to dynamically update the values | ||
| /// of the icon as needed. | ||
| /// @type Map | ||
| $rmd-tree-theme-values: ( | ||
| incrementor: $rmd-tree-item-padding-incrementor, | ||
| base-padding: $rmd-tree-item-padding-base, | ||
| ) !default; |
| @import 'mixins'; | ||
| @include react-md-tree; |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
338349
-8.64%135
-10.6%5836
-8.56%Updated
Updated
Updated
Updated
Updated