🚨 Latest Research:Tanstack npm Packages Compromised in Ongoing Mini Shai-Hulud Supply-Chain Attack.Learn More
Socket
Book a DemoSign in
Socket

@react-md/tree

Package Overview
Dependencies
Maintainers
1
Versions
69
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@react-md/tree - npm Package Compare versions

Comparing version
2.9.0
to
2.9.1
+12
-0
CHANGELOG.md

@@ -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
);
}
////
/// @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;