@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.
Files changed (30) hide show
  1. package/components/TreeList/TreeList.d.ts +2 -0
  2. package/components/TreeList/TreeList.js +37 -0
  3. package/components/TreeList/TreeList.module.css.d.ts +2 -0
  4. package/components/TreeList/TreeList.module.css.js +24 -0
  5. package/components/TreeList/TreeList.module.css.json +1 -0
  6. package/components/TreeList/TreeList.types.d.ts +60 -0
  7. package/components/TreeList/TreeList.types.js +1 -0
  8. package/components/TreeList/components/ChevronIcon.d.ts +5 -0
  9. package/components/TreeList/components/ChevronIcon.js +8 -0
  10. package/components/TreeList/components/TreeLevelLines/TreeLevelLines.d.ts +2 -0
  11. package/components/TreeList/components/TreeLevelLines/TreeLevelLines.js +16 -0
  12. package/components/TreeList/components/TreeLevelLines/TreeLevelLines.module.css.d.ts +2 -0
  13. package/components/TreeList/components/TreeLevelLines/TreeLevelLines.module.css.js +52 -0
  14. package/components/TreeList/components/TreeLevelLines/TreeLevelLines.module.css.json +1 -0
  15. package/components/TreeList/components/TreeLevelLines/TreeLevelLines.types.d.ts +4 -0
  16. package/components/TreeList/components/TreeLevelLines/TreeLevelLines.types.js +1 -0
  17. package/components/TreeList/components/TreeNode/TreeNode.d.ts +2 -0
  18. package/components/TreeList/components/TreeNode/TreeNode.js +14 -0
  19. package/components/TreeList/components/TreeNode/TreeNode.module.css.d.ts +2 -0
  20. package/components/TreeList/components/TreeNode/TreeNode.module.css.js +42 -0
  21. package/components/TreeList/components/TreeNode/TreeNode.module.css.json +1 -0
  22. package/components/TreeList/components/TreeNode/TreeNode.types.d.ts +15 -0
  23. package/components/TreeList/components/TreeNode/TreeNode.types.js +1 -0
  24. package/components/TreeList/helpers.d.ts +3 -0
  25. package/components/TreeList/helpers.js +27 -0
  26. package/components/TreeList/index.d.ts +2 -0
  27. package/components/TreeList/index.js +1 -0
  28. package/package.json +5 -4
  29. package/packages/design/index.d.ts +1 -0
  30. package/packages/design/index.js +1 -0
@@ -0,0 +1,2 @@
1
+ import type { TreeListProps } from "./TreeList.types";
2
+ export declare const TreeList: import("react").MemoExoticComponent<({ data, LabelComponent, expandedKeys: expandedKeysProp, onExpand, }: TreeListProps) => import("react/jsx-runtime").JSX.Element>;
@@ -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,2 @@
1
+ import json from './TreeList.module.css.json';
2
+ export default json;
@@ -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,5 @@
1
+ type Props = {
2
+ expanded: boolean;
3
+ };
4
+ export declare const ChevronIcon: ({ expanded }: Props) => import("react/jsx-runtime").JSX.Element;
5
+ 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,2 @@
1
+ import type { TreeLevelLinesProps } from "./TreeLevelLines.types";
2
+ export declare const TreeLevelLines: import("react").MemoExoticComponent<({ levelLines, isLast }: TreeLevelLinesProps) => import("react/jsx-runtime").JSX.Element>;
@@ -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,2 @@
1
+ import json from './TreeLevelLines.module.css.json';
2
+ export default json;
@@ -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,4 @@
1
+ export type TreeLevelLinesProps = {
2
+ levelLines: boolean[];
3
+ isLast: boolean;
4
+ };
@@ -0,0 +1,2 @@
1
+ import type { TreeNodeProps } from "./TreeNode.types";
2
+ export declare const TreeNode: import("react").MemoExoticComponent<({ id, node, depth, isLeaf, isExpanded, levelLines, isLast, onToggle, LabelComponent, }: TreeNodeProps) => import("react/jsx-runtime").JSX.Element>;
@@ -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,2 @@
1
+ import json from './TreeNode.module.css.json';
2
+ export default json;
@@ -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,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,2 @@
1
+ export * from "./TreeList";
2
+ export type * from "./TreeList.types";
@@ -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.1",
3
+ "version": "0.0.2",
4
4
  "main": "packages/design/index.js",
5
5
  "description": "Reltio Design System",
6
6
  "peerDependencies": {
7
- "react": "^17.0.2",
8
- "react-dom": "^17.0.2"
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",
@@ -1 +1,2 @@
1
1
  export * from "../../components/Button";
2
+ export * from "../../components/TreeList";
@@ -1 +1,2 @@
1
1
  export * from "../../components/Button";
2
+ export * from "../../components/TreeList";