@reltio/design 0.0.1 → 0.0.2
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/components/TreeList/TreeList.d.ts +2 -0
- package/components/TreeList/TreeList.js +37 -0
- package/components/TreeList/TreeList.module.css.d.ts +2 -0
- package/components/TreeList/TreeList.module.css.js +24 -0
- package/components/TreeList/TreeList.module.css.json +1 -0
- package/components/TreeList/TreeList.types.d.ts +60 -0
- package/components/TreeList/TreeList.types.js +1 -0
- package/components/TreeList/components/ChevronIcon.d.ts +5 -0
- package/components/TreeList/components/ChevronIcon.js +8 -0
- package/components/TreeList/components/TreeLevelLines/TreeLevelLines.d.ts +2 -0
- package/components/TreeList/components/TreeLevelLines/TreeLevelLines.js +16 -0
- package/components/TreeList/components/TreeLevelLines/TreeLevelLines.module.css.d.ts +2 -0
- package/components/TreeList/components/TreeLevelLines/TreeLevelLines.module.css.js +52 -0
- package/components/TreeList/components/TreeLevelLines/TreeLevelLines.module.css.json +1 -0
- package/components/TreeList/components/TreeLevelLines/TreeLevelLines.types.d.ts +4 -0
- package/components/TreeList/components/TreeLevelLines/TreeLevelLines.types.js +1 -0
- package/components/TreeList/components/TreeNode/TreeNode.d.ts +2 -0
- package/components/TreeList/components/TreeNode/TreeNode.js +14 -0
- package/components/TreeList/components/TreeNode/TreeNode.module.css.d.ts +2 -0
- package/components/TreeList/components/TreeNode/TreeNode.module.css.js +42 -0
- package/components/TreeList/components/TreeNode/TreeNode.module.css.json +1 -0
- package/components/TreeList/components/TreeNode/TreeNode.types.d.ts +15 -0
- package/components/TreeList/components/TreeNode/TreeNode.types.js +1 -0
- package/components/TreeList/helpers.d.ts +3 -0
- package/components/TreeList/helpers.js +27 -0
- package/components/TreeList/index.d.ts +2 -0
- package/components/TreeList/index.js +1 -0
- package/package.json +5 -4
- package/packages/design/index.d.ts +1 -0
- package/packages/design/index.js +1 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import Tree from "rc-tree";
|
|
3
|
+
import { memo, useCallback, useMemo, useState } from "react";
|
|
4
|
+
import { TreeNode } from "./components/TreeNode/TreeNode";
|
|
5
|
+
import { getLevelLinesData, transformTreeData } from "./helpers";
|
|
6
|
+
import styles from "./TreeList.module.css";
|
|
7
|
+
export const TreeList = memo(({ data, LabelComponent, expandedKeys: expandedKeysProp, onExpand, }) => {
|
|
8
|
+
const topLevelKeys = useMemo(() => data.map((item) => item.id), [data]);
|
|
9
|
+
const isControlled = expandedKeysProp !== undefined;
|
|
10
|
+
const [expandedKeys, setExpandedKeys] = useState(() => isControlled ? new Set() : new Set(topLevelKeys));
|
|
11
|
+
const rcData = useMemo(() => transformTreeData(data), [data]);
|
|
12
|
+
const levelLinesMap = useMemo(() => getLevelLinesData(rcData), [rcData]);
|
|
13
|
+
const expandedSet = useMemo(() => isControlled ? new Set(expandedKeysProp ?? []) : expandedKeys, [expandedKeysProp, expandedKeys, isControlled]);
|
|
14
|
+
const expandedArray = useMemo(() => Array.from(expandedSet), [expandedSet]);
|
|
15
|
+
const updateExpandedKeys = useCallback((keys) => {
|
|
16
|
+
if (isControlled) {
|
|
17
|
+
onExpand?.(keys);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
setExpandedKeys(new Set(keys));
|
|
21
|
+
onExpand?.(keys);
|
|
22
|
+
}, [isControlled, onExpand]);
|
|
23
|
+
const handleToggle = useCallback((id, isExpanded) => {
|
|
24
|
+
const next = new Set(expandedSet);
|
|
25
|
+
isExpanded ? next.delete(id) : next.add(id);
|
|
26
|
+
updateExpandedKeys(Array.from(next));
|
|
27
|
+
}, [expandedSet, updateExpandedKeys]);
|
|
28
|
+
const renderTitle = useCallback((node) => {
|
|
29
|
+
const raw = node.data.raw;
|
|
30
|
+
const isLeafNode = !!node.isLeaf;
|
|
31
|
+
const isExpanded = expandedSet.has(node.key);
|
|
32
|
+
const [levelLines, isLast] = levelLinesMap[node.key] ?? [[], false];
|
|
33
|
+
return (_jsx(TreeNode, { id: node.key, node: raw, depth: node.data.depth, isLeaf: isLeafNode, isExpanded: isExpanded, levelLines: levelLines, isLast: isLast, onToggle: handleToggle, LabelComponent: LabelComponent }));
|
|
34
|
+
}, [expandedSet, levelLinesMap, LabelComponent, handleToggle]);
|
|
35
|
+
return (_jsx("div", { className: styles.root, children: _jsx(Tree, { treeData: rcData, expandAction: false, virtual: false, selectable: false, expandedKeys: expandedArray, onExpand: (keys) => updateExpandedKeys(keys), showIcon: false, titleRender: renderTitle }) }));
|
|
36
|
+
});
|
|
37
|
+
TreeList.displayName = "TreeList";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import styleInject from 'style-inject';
|
|
2
|
+
import json from './TreeList.module.css.json';
|
|
3
|
+
styleInject(`
|
|
4
|
+
._root_k7z3s_1 {
|
|
5
|
+
--reltio-tree-list-font-family: inherit;
|
|
6
|
+
--reltio-tree-list-font-size: inherit;
|
|
7
|
+
--reltio-tree-list-text-color: inherit;
|
|
8
|
+
--reltio-tree-list-background: inherit;
|
|
9
|
+
--reltio-tree-list-line-height: inherit;
|
|
10
|
+
display: block;
|
|
11
|
+
overflow: auto;
|
|
12
|
+
font-family: var(--reltio-tree-list-font-family, system-ui, sans-serif);
|
|
13
|
+
font-size: var(--reltio-tree-list-font-size, 14px);
|
|
14
|
+
color: var(--reltio-tree-list-text-color, #1a1a1a);
|
|
15
|
+
background: var(--reltio-tree-list-background, transparent);
|
|
16
|
+
border: none;
|
|
17
|
+
border-radius: var(--reltio-tree-list-border-radius, 0);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
._rc-tree-treenode_k7z3s_17 {
|
|
21
|
+
list-style: none;
|
|
22
|
+
}
|
|
23
|
+
`);
|
|
24
|
+
export default json;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "root": "_root_k7z3s_1", "rc-tree-treenode": "_rc-tree-treenode_k7z3s_17" }
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { ComponentType } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Unique identifier that keeps tree nodes stable across renders.
|
|
4
|
+
*/
|
|
5
|
+
export type TreeKey = string | number;
|
|
6
|
+
/**
|
|
7
|
+
* Tree node shape. Children create nested levels.
|
|
8
|
+
*/
|
|
9
|
+
export type TreeItem = {
|
|
10
|
+
/** Stable id of the node. */
|
|
11
|
+
id: TreeKey;
|
|
12
|
+
/** Text label rendered by default `TreeList`. */
|
|
13
|
+
label: string;
|
|
14
|
+
/** Optional nested children. */
|
|
15
|
+
children?: TreeItem[];
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Internal rc-tree node representation used for rendering.
|
|
19
|
+
*/
|
|
20
|
+
export type RcTreeNodeData<T> = {
|
|
21
|
+
key: TreeKey;
|
|
22
|
+
title: null;
|
|
23
|
+
isLeaf?: boolean;
|
|
24
|
+
data: {
|
|
25
|
+
raw: T;
|
|
26
|
+
depth: number;
|
|
27
|
+
parentId?: TreeKey;
|
|
28
|
+
};
|
|
29
|
+
children?: RcTreeNodeData<T>[];
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Props for the TreeList component.
|
|
33
|
+
*/
|
|
34
|
+
export type TreeListProps = {
|
|
35
|
+
/** Hierarchical data to render.
|
|
36
|
+
* `type TreeItem = {id: TreeKey; label: string; children?: TreeItem[]}` `type TreeKey = string | number`
|
|
37
|
+
* @example
|
|
38
|
+
* [
|
|
39
|
+
* { id: "1", label: "Node 1", children: [
|
|
40
|
+
* { id: "1.1", label: "Node 1.1" },
|
|
41
|
+
* { id: "1.2", label: "Node 1.2" }
|
|
42
|
+
* ] },
|
|
43
|
+
* { id: "2", label: "Node 2", children: [
|
|
44
|
+
* { id: "2.1", label: "Node 2.1" }
|
|
45
|
+
* ] }
|
|
46
|
+
* ]
|
|
47
|
+
*/
|
|
48
|
+
data: TreeItem[];
|
|
49
|
+
/** Custom renderer for the node label. */
|
|
50
|
+
LabelComponent?: ComponentType<{
|
|
51
|
+
data: TreeItem;
|
|
52
|
+
}>;
|
|
53
|
+
/** Controlled list of expanded node ids. */
|
|
54
|
+
expandedKeys?: TreeKey[];
|
|
55
|
+
/**
|
|
56
|
+
* Called when the expanded state changes (controlled mode).
|
|
57
|
+
* Provides the resulting expanded keys list.
|
|
58
|
+
*/
|
|
59
|
+
onExpand?: (keys: TreeKey[]) => void;
|
|
60
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
export const ChevronIcon = ({ expanded }) => {
|
|
3
|
+
return (_jsx("svg", { viewBox: "0 0 24 24", style: {
|
|
4
|
+
transform: expanded ? "rotate(0deg)" : "rotate(-90deg)",
|
|
5
|
+
transition: "transform 0.2s ease",
|
|
6
|
+
transformOrigin: "50% 50%",
|
|
7
|
+
}, "aria-hidden": "true", children: _jsx("polygon", { points: "6,9 18,9 12,16", fill: "currentColor" }) }));
|
|
8
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { memo } from "react";
|
|
3
|
+
import { classNames } from "../../../../utils/classNames";
|
|
4
|
+
import styles from "./TreeLevelLines.module.css";
|
|
5
|
+
const LevelLine = memo(({ needDrawLine = false, isLastLevelLine = false, drawHorizontalLine = false, }) => (_jsx("div", { className: classNames(styles.levelLine, needDrawLine && styles.showLine, isLastLevelLine && styles.lastLevelLine, drawHorizontalLine && styles.horizontalLine) })));
|
|
6
|
+
export const TreeLevelLines = memo(({ levelLines, isLast = false }) => {
|
|
7
|
+
const needDrawLines = levelLines;
|
|
8
|
+
const isRoot = needDrawLines.length === 0;
|
|
9
|
+
const level = needDrawLines.length + 2;
|
|
10
|
+
if (isRoot) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
return (_jsxs("div", { className: classNames(styles.levelLines), children: [needDrawLines.map((needDrawLine, index) => (_jsx(LevelLine, { needDrawLine: needDrawLine }, `${index}-${needDrawLine}`))), _jsx(LevelLine, { needDrawLine: true, drawHorizontalLine: true, isLastLevelLine: isLast }, level)] }));
|
|
14
|
+
});
|
|
15
|
+
LevelLine.displayName = "LevelLine";
|
|
16
|
+
TreeLevelLines.displayName = "TreeLevelLines";
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import styleInject from 'style-inject';
|
|
2
|
+
import json from './TreeLevelLines.module.css.json';
|
|
3
|
+
styleInject(`
|
|
4
|
+
._levelLines_12unh_1 {
|
|
5
|
+
position: absolute;
|
|
6
|
+
display: flex;
|
|
7
|
+
padding-left: 0;
|
|
8
|
+
cursor: initial;
|
|
9
|
+
bottom: 0;
|
|
10
|
+
top: 0;
|
|
11
|
+
z-index: 0;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
._levelLine_12unh_1 {
|
|
15
|
+
padding-left: var(--reltio-tree-list-indent-size, 16px);
|
|
16
|
+
height: 100%;
|
|
17
|
+
position: relative;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
._showLine_12unh_17::after {
|
|
21
|
+
content: "";
|
|
22
|
+
position: absolute;
|
|
23
|
+
height: 100%;
|
|
24
|
+
width: 1px;
|
|
25
|
+
left: calc(var(--reltio-tree-list-indent-size, 16px) - 2px);
|
|
26
|
+
top: 0;
|
|
27
|
+
bottom: 0;
|
|
28
|
+
background-color: var(--reltio-tree-list-line-color, rgba(0, 0, 0, 0.08));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
._lastLevelLine_12unh_28::after {
|
|
32
|
+
height: 50%;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
._lastLevelLine_12unh_28 {
|
|
36
|
+
padding-left: calc(
|
|
37
|
+
var(--reltio-tree-list-indent-size, 16px) +
|
|
38
|
+
(var(--reltio-tree-list-toggle-size, 26px) / 2)
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
._horizontalLine_12unh_39::before {
|
|
43
|
+
content: "";
|
|
44
|
+
height: 1px;
|
|
45
|
+
width: 5px;
|
|
46
|
+
position: absolute;
|
|
47
|
+
top: 50%;
|
|
48
|
+
left: calc(var(--reltio-tree-list-indent-size, 16px) - 2px);
|
|
49
|
+
background-color: var(--reltio-tree-list-line-color, rgba(0, 0, 0, 0.08));
|
|
50
|
+
}
|
|
51
|
+
`);
|
|
52
|
+
export default json;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "levelLines": "_levelLines_12unh_1", "levelLine": "_levelLine_12unh_1", "showLine": "_showLine_12unh_17", "lastLevelLine": "_lastLevelLine_12unh_28", "horizontalLine": "_horizontalLine_12unh_39" }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { memo, useCallback } from "react";
|
|
3
|
+
import { classNames } from "../../../../utils/classNames";
|
|
4
|
+
import { ChevronIcon } from "../ChevronIcon";
|
|
5
|
+
import { TreeLevelLines } from "../TreeLevelLines/TreeLevelLines";
|
|
6
|
+
import styles from "./TreeNode.module.css";
|
|
7
|
+
export const TreeNode = memo(({ id, node, depth, isLeaf, isExpanded, levelLines, isLast, onToggle, LabelComponent, }) => {
|
|
8
|
+
const handleToggleClick = useCallback((event) => {
|
|
9
|
+
event.stopPropagation();
|
|
10
|
+
onToggle(id, isExpanded);
|
|
11
|
+
}, [onToggle, id, isExpanded]);
|
|
12
|
+
return (_jsxs("div", { className: classNames(styles.wrapper), "data-depth": depth, children: [_jsx(TreeLevelLines, { levelLines: levelLines, isLast: isLast }), _jsx("span", { className: styles.indent, style: { ["--depth"]: `${depth}` } }), isLeaf ? (_jsx("span", { className: styles.toggle, "aria-hidden": "true" })) : (_jsx("button", { type: "button", className: styles.toggle, "aria-label": isExpanded ? "Collapse" : "Expand", onClick: handleToggleClick, children: _jsx(ChevronIcon, { expanded: isExpanded }) })), LabelComponent ? _jsx(LabelComponent, { data: node }) : node.label] }));
|
|
13
|
+
});
|
|
14
|
+
TreeNode.displayName = "TreeNode";
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import styleInject from 'style-inject';
|
|
2
|
+
import json from './TreeNode.module.css.json';
|
|
3
|
+
styleInject(`
|
|
4
|
+
._wrapper_67wfw_1 {
|
|
5
|
+
display: flex;
|
|
6
|
+
align-items: center;
|
|
7
|
+
line-height: var(--reltio-tree-list-line-height, 1.5);
|
|
8
|
+
padding: var(--reltio-tree-list-row-padding-block, 2px)
|
|
9
|
+
var(--reltio-tree-list-row-padding-inline, 4px);
|
|
10
|
+
position: relative;
|
|
11
|
+
z-index: 1;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
._indent_67wfw_11 {
|
|
15
|
+
display: inline-block;
|
|
16
|
+
width: calc(var(--depth, 1) * var(--reltio-tree-list-indent-size, 16px));
|
|
17
|
+
flex: 0 0 auto;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
._toggle_67wfw_17 {
|
|
21
|
+
display: inline-flex;
|
|
22
|
+
align-items: center;
|
|
23
|
+
justify-content: center;
|
|
24
|
+
width: var(--reltio-tree-list-toggle-size, 26px);
|
|
25
|
+
height: var(--reltio-tree-list-toggle-size, 26px);
|
|
26
|
+
border: none;
|
|
27
|
+
background: none;
|
|
28
|
+
color: var(--reltio-tree-list-toggle-color, #5f6368);
|
|
29
|
+
cursor: pointer;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
._actions_67wfw_29 {
|
|
33
|
+
margin-left: auto;
|
|
34
|
+
opacity: 0;
|
|
35
|
+
transition: opacity 0.12s ease;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
._wrapper_67wfw_1:hover ._actions_67wfw_29 {
|
|
39
|
+
opacity: 1;
|
|
40
|
+
}
|
|
41
|
+
`);
|
|
42
|
+
export default json;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "wrapper": "_wrapper_67wfw_1", "indent": "_indent_67wfw_11", "toggle": "_toggle_67wfw_17", "actions": "_actions_67wfw_29" }
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ComponentType } from "react";
|
|
2
|
+
import type { TreeItem, TreeKey } from "../../TreeList.types";
|
|
3
|
+
export type TreeNodeProps = {
|
|
4
|
+
id: TreeKey;
|
|
5
|
+
node: TreeItem;
|
|
6
|
+
depth: number;
|
|
7
|
+
isLeaf: boolean;
|
|
8
|
+
isExpanded: boolean;
|
|
9
|
+
levelLines: boolean[];
|
|
10
|
+
isLast: boolean;
|
|
11
|
+
onToggle: (id: TreeKey, expanded: boolean) => void;
|
|
12
|
+
LabelComponent?: ComponentType<{
|
|
13
|
+
data: TreeItem;
|
|
14
|
+
}>;
|
|
15
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { RcTreeNodeData, TreeItem, TreeKey } from "./TreeList.types";
|
|
2
|
+
export declare const getLevelLinesData: <T>(treeData: ReadonlyArray<RcTreeNodeData<T>>) => Record<TreeKey, [boolean[], boolean]>;
|
|
3
|
+
export declare const transformTreeData: (data: TreeItem[], depth?: number, parentId?: TreeKey) => RcTreeNodeData<TreeItem>[];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export const getLevelLinesData = (treeData) => {
|
|
2
|
+
const acc = {};
|
|
3
|
+
const traverse = (nodes, prefix = [], depth = 0) => {
|
|
4
|
+
for (let index = 0; index < nodes.length; index++) {
|
|
5
|
+
const node = nodes[index];
|
|
6
|
+
const isLast = index === nodes.length - 1;
|
|
7
|
+
acc[node.key] = [prefix, isLast];
|
|
8
|
+
if (node.children?.length) {
|
|
9
|
+
const nextPrefix = depth === 0 ? [...prefix, false] : [...prefix, !isLast];
|
|
10
|
+
traverse(node.children, nextPrefix, depth + 1);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
traverse(treeData);
|
|
15
|
+
return acc;
|
|
16
|
+
};
|
|
17
|
+
export const transformTreeData = (data, depth = 1, parentId) => {
|
|
18
|
+
return data.map((item) => ({
|
|
19
|
+
key: item.id,
|
|
20
|
+
title: null,
|
|
21
|
+
isLeaf: !item.children?.length,
|
|
22
|
+
data: { raw: item, depth, parentId },
|
|
23
|
+
children: item.children
|
|
24
|
+
? transformTreeData(item.children, depth + 1, item.id)
|
|
25
|
+
: undefined,
|
|
26
|
+
}));
|
|
27
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./TreeList";
|
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reltio/design",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"main": "packages/design/index.js",
|
|
5
5
|
"description": "Reltio Design System",
|
|
6
6
|
"peerDependencies": {
|
|
7
|
-
"react": "
|
|
8
|
-
"react-dom": "
|
|
7
|
+
"react": ">=17 <20",
|
|
8
|
+
"react-dom": ">=17 <20"
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"style-inject": "^0.3.0"
|
|
11
|
+
"style-inject": "^0.3.0",
|
|
12
|
+
"rc-tree": "^5.13.1"
|
|
12
13
|
},
|
|
13
14
|
"scripts": {
|
|
14
15
|
"build": "node build-css.mjs && tsc && tsc-alias",
|
package/packages/design/index.js
CHANGED