@atlaskit/charlie-hierarchy 0.0.0

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/CHANGELOG.md ADDED
@@ -0,0 +1 @@
1
+ # @atlaskit/charlie-hierarchy
package/LICENSE.md ADDED
@@ -0,0 +1,11 @@
1
+ Copyright 2023 Atlassian Pty Ltd
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
4
+ compliance with the License. You may obtain a copy of the License at
5
+
6
+ http://www.apache.org/licenses/LICENSE-2.0
7
+
8
+ Unless required by applicable law or agreed to in writing, software distributed under the License is
9
+ distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
10
+ implied. See the License for the specific language governing permissions and limitations under the
11
+ License.
package/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # CharlieHierarchy
2
+
3
+ Add a description here.
4
+
5
+ ## Usage
6
+
7
+ `import CharlieHierarchy from '@atlaskit/charlie-hierarchy';`
8
+
9
+ Detailed docs and example usage can be found [here](https://atlaskit.atlassian.com/packages/technology-innovation/charlie-hierarchy).
@@ -0,0 +1,5 @@
1
+ ._18m9ewfl{overflow-y:visible}
2
+ ._1reoewfl{overflow-x:visible}
3
+ ._1tktglyw{touch-action:none}
4
+ ._kqswh2mm{position:relative}
5
+ ._kqswstnw{position:absolute}
@@ -0,0 +1,164 @@
1
+ /* charlie-hierarchy.tsx generated by @compiled/babel-plugin v0.36.1 */
2
+ "use strict";
3
+
4
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.CharlieHierarchy = void 0;
9
+ require("./charlie-hierarchy.compiled.css");
10
+ var _runtime = require("@compiled/react/runtime");
11
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
12
+ var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
13
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
14
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
15
+ var _react = _interopRequireDefault(require("react"));
16
+ var _group = require("@visx/group");
17
+ var _hierarchy = require("@visx/hierarchy");
18
+ var _shape = require("@visx/shape");
19
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
20
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } /**
21
+ * CharlieHierarchy is meant to be a generic reusable component for building SVG rendered trees.
22
+ * It is a wrapper around the visx Tree component that provides a more declarative API.
23
+ * https://airbnb.io/visx/docs/hierarchy#Tree
24
+ * Common use cases can be handled in the CharlieHierarchy component to allow for a quicker entry point to creating trees.
25
+ */
26
+ var staticStyles = {
27
+ hierarchyWrapper: "_kqswh2mm",
28
+ nodeGroupWrapper: "_kqswstnw",
29
+ nodeWrapper: "_1reoewfl _18m9ewfl _kqswstnw",
30
+ svg: "_1reoewfl _18m9ewfl _kqswstnw",
31
+ zoom: "_1tktglyw"
32
+ };
33
+ var CharlieHierarchy = exports.CharlieHierarchy = function CharlieHierarchy(props) {
34
+ var _props$size$, _props$size, _props$size$2, _props$size2, _props$nodeSize$, _props$nodeSize, _props$nodeSize$2, _props$nodeSize2, _props$top, _props$left, _props$renderDependen, _styles$transformMatr, _props$styles2;
35
+ var _React$useTransition = _react.default.useTransition(),
36
+ _React$useTransition2 = (0, _slicedToArray2.default)(_React$useTransition, 2),
37
+ isSuspending = _React$useTransition2[0],
38
+ startSuspending = _React$useTransition2[1];
39
+ var styles = _objectSpread(_objectSpread({}, {
40
+ padding: {
41
+ above: 100,
42
+ adjacent: 30
43
+ }
44
+ }), props.styles);
45
+ var containerHeight = (_props$size$ = (_props$size = props.size) === null || _props$size === void 0 ? void 0 : _props$size[1]) !== null && _props$size$ !== void 0 ? _props$size$ : 0;
46
+ var containerWidth = (_props$size$2 = (_props$size2 = props.size) === null || _props$size2 === void 0 ? void 0 : _props$size2[0]) !== null && _props$size$2 !== void 0 ? _props$size$2 : 0;
47
+ var nodeWidth = (_props$nodeSize$ = (_props$nodeSize = props.nodeSize) === null || _props$nodeSize === void 0 ? void 0 : _props$nodeSize[0]) !== null && _props$nodeSize$ !== void 0 ? _props$nodeSize$ : 0;
48
+ var nodeHeight = (_props$nodeSize$2 = (_props$nodeSize2 = props.nodeSize) === null || _props$nodeSize2 === void 0 ? void 0 : _props$nodeSize2[1]) !== null && _props$nodeSize$2 !== void 0 ? _props$nodeSize$2 : 0;
49
+ var nodeWidthWithPadding = nodeWidth + styles.padding.adjacent;
50
+ var nodeHeightWithPadding = nodeHeight + styles.padding.above;
51
+ var nodeSize = [nodeWidthWithPadding, nodeHeightWithPadding];
52
+ var root = props.root;
53
+ var top = (_props$top = props.top) !== null && _props$top !== void 0 ? _props$top : 0;
54
+ var left = (_props$left = props.left) !== null && _props$left !== void 0 ? _props$left : 0;
55
+ var zoom = props === null || props === void 0 ? void 0 : props.zoom;
56
+ var cursor = zoom !== null && zoom !== void 0 && zoom.isDragging ? 'grabbing' : 'grab';
57
+ var children = props.children;
58
+ var renderDependencies = (_props$renderDependen = props.renderDependencies) !== null && _props$renderDependen !== void 0 ? _props$renderDependen : [];
59
+
60
+ /**
61
+ * If zoom is enabled, we need to apply the transform matrix to the SVG.
62
+ * If not, then use the static transform matrix provided in the styles prop.
63
+ * If no transform matrix is provided, then don't apply any transform.
64
+ */
65
+ var transformMatrix = (_styles$transformMatr = styles.transformMatrix) !== null && _styles$transformMatr !== void 0 ? _styles$transformMatr : {
66
+ scaleX: 1,
67
+ scaleY: 1,
68
+ skewX: 0,
69
+ skewY: 0,
70
+ translateX: document.body.clientWidth / 2,
71
+ translateY: 120
72
+ };
73
+ var transform = zoom ? zoom === null || zoom === void 0 ? void 0 : zoom.toString() : transformMatrix ? "matrix(".concat(transformMatrix.scaleX, ", ").concat(transformMatrix.skewX, ", ").concat(transformMatrix.skewY, ", ").concat(transformMatrix.scaleY, ", ").concat(transformMatrix.translateX, ", ").concat(transformMatrix.translateY, ")") : undefined;
74
+ var edges = _react.default.useMemo(function () {
75
+ return /*#__PURE__*/_react.default.createElement(_hierarchy.Tree, {
76
+ root: root,
77
+ top: top,
78
+ left: left,
79
+ nodeSize: nodeSize
80
+ }, function (tree) {
81
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, tree.links().map(function (link, linkIndex) {
82
+ var _props$styles$lineAtt, _props$styles;
83
+ return /*#__PURE__*/_react.default.createElement(_shape.LinkVerticalStep, (0, _extends2.default)({
84
+ key: "link-".concat(linkIndex),
85
+ data: link,
86
+ stroke: "var(--ds-border-accent-gray, #758195)",
87
+ strokeWidth: "1",
88
+ fill: "none",
89
+ opacity: 1,
90
+ percent: 0.5
91
+ }, (_props$styles$lineAtt = (_props$styles = props.styles) === null || _props$styles === void 0 ? void 0 : _props$styles.lineAttributes) !== null && _props$styles$lineAtt !== void 0 ? _props$styles$lineAtt : {}));
92
+ }));
93
+ });
94
+ // There are cases where the parent component will want to render the tree
95
+ // depending on certain props. so we need to pass the renderDependencies so the
96
+ // tree will re-render when the dependencies change.
97
+ // eslint-disable-next-line react-hooks/exhaustive-deps
98
+ }, [].concat((0, _toConsumableArray2.default)(renderDependencies), [(_props$styles2 = props.styles) === null || _props$styles2 === void 0 ? void 0 : _props$styles2.lineAttributes]));
99
+ var nodes = _react.default.useMemo(function () {
100
+ return /*#__PURE__*/_react.default.createElement(_hierarchy.Tree, {
101
+ root: root,
102
+ top: top,
103
+ left: left,
104
+ nodeSize: nodeSize
105
+ }, function (tree) {
106
+ var descendants = tree.descendants();
107
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, descendants.map(function (node, index) {
108
+ var top = node.y - nodeHeight / 2;
109
+ var left = node.x - nodeWidth / 2;
110
+ return /*#__PURE__*/_react.default.createElement("div", {
111
+ key: "tree-node-".concat(index),
112
+ style: {
113
+ top: top,
114
+ left: left,
115
+ width: "".concat(nodeWidth, "px"),
116
+ height: "".concat(nodeHeight, "px")
117
+ },
118
+ className: (0, _runtime.ax)([staticStyles.nodeWrapper])
119
+ }, children(node, isSuspending, startSuspending));
120
+ }));
121
+ });
122
+ // There are cases where the parent component will want to render the tree
123
+ // depending on certain props. so we need to pass the renderDependencies so the
124
+ // tree will re-render when the dependencies change.
125
+ // eslint-disable-next-line react-hooks/exhaustive-deps
126
+ }, [].concat((0, _toConsumableArray2.default)(renderDependencies), [nodeHeight, isSuspending, nodeWidth, children]));
127
+ return /*#__PURE__*/_react.default.createElement("div", {
128
+ style: {
129
+ height: "".concat(containerHeight, "px"),
130
+ width: "".concat(containerWidth, "px")
131
+ },
132
+ className: (0, _runtime.ax)([staticStyles.hierarchyWrapper])
133
+ }, /*#__PURE__*/_react.default.createElement("svg", {
134
+ width: containerWidth,
135
+ height: containerHeight,
136
+ style: {
137
+ cursor: "".concat(cursor)
138
+ },
139
+ ref: zoom ? zoom.containerRef : undefined,
140
+ className: (0, _runtime.ax)([staticStyles.svg, zoom && ""])
141
+ }, zoom && /*#__PURE__*/_react.default.createElement("rect", {
142
+ width: containerWidth,
143
+ height: containerHeight,
144
+ fill: "transparent",
145
+ onTouchStart: zoom.dragStart,
146
+ onTouchMove: zoom.dragMove,
147
+ onTouchEnd: zoom.dragEnd,
148
+ onMouseDown: zoom.dragStart,
149
+ onMouseMove: zoom.dragMove,
150
+ onMouseUp: zoom.dragEnd,
151
+ onMouseLeave: function onMouseLeave() {
152
+ if (zoom.isDragging) {
153
+ zoom.dragEnd();
154
+ }
155
+ }
156
+ }), /*#__PURE__*/_react.default.createElement(_group.Group, {
157
+ transform: transform
158
+ }, edges)), /*#__PURE__*/_react.default.createElement("div", {
159
+ style: {
160
+ transform: "".concat(transform)
161
+ },
162
+ className: (0, _runtime.ax)([staticStyles.nodeGroupWrapper])
163
+ }, nodes));
164
+ };
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "CharlieHierarchy", {
7
+ enumerable: true,
8
+ get: function get() {
9
+ return _charlieHierarchy.CharlieHierarchy;
10
+ }
11
+ });
12
+ var _charlieHierarchy = require("./charlie-hierarchy/charlie-hierarchy");
@@ -0,0 +1,5 @@
1
+ ._18m9ewfl{overflow-y:visible}
2
+ ._1reoewfl{overflow-x:visible}
3
+ ._1tktglyw{touch-action:none}
4
+ ._kqswh2mm{position:relative}
5
+ ._kqswstnw{position:absolute}
@@ -0,0 +1,154 @@
1
+ /* charlie-hierarchy.tsx generated by @compiled/babel-plugin v0.36.1 */
2
+ import _extends from "@babel/runtime/helpers/extends";
3
+ import "./charlie-hierarchy.compiled.css";
4
+ import { ax, ix } from "@compiled/react/runtime";
5
+ /**
6
+ * CharlieHierarchy is meant to be a generic reusable component for building SVG rendered trees.
7
+ * It is a wrapper around the visx Tree component that provides a more declarative API.
8
+ * https://airbnb.io/visx/docs/hierarchy#Tree
9
+ * Common use cases can be handled in the CharlieHierarchy component to allow for a quicker entry point to creating trees.
10
+ */
11
+
12
+ import React from 'react';
13
+ import { Group } from '@visx/group';
14
+ import { Tree } from '@visx/hierarchy';
15
+ import { LinkVerticalStep } from '@visx/shape';
16
+ const staticStyles = {
17
+ hierarchyWrapper: "_kqswh2mm",
18
+ nodeGroupWrapper: "_kqswstnw",
19
+ nodeWrapper: "_1reoewfl _18m9ewfl _kqswstnw",
20
+ svg: "_1reoewfl _18m9ewfl _kqswstnw",
21
+ zoom: "_1tktglyw"
22
+ };
23
+ export const CharlieHierarchy = props => {
24
+ var _props$size$, _props$size, _props$size$2, _props$size2, _props$nodeSize$, _props$nodeSize, _props$nodeSize$2, _props$nodeSize2, _props$top, _props$left, _props$renderDependen, _styles$transformMatr, _props$styles2;
25
+ const [isSuspending, startSuspending] = React.useTransition();
26
+ const styles = {
27
+ ...{
28
+ padding: {
29
+ above: 100,
30
+ adjacent: 30
31
+ }
32
+ },
33
+ ...props.styles
34
+ };
35
+ const containerHeight = (_props$size$ = (_props$size = props.size) === null || _props$size === void 0 ? void 0 : _props$size[1]) !== null && _props$size$ !== void 0 ? _props$size$ : 0;
36
+ const containerWidth = (_props$size$2 = (_props$size2 = props.size) === null || _props$size2 === void 0 ? void 0 : _props$size2[0]) !== null && _props$size$2 !== void 0 ? _props$size$2 : 0;
37
+ const nodeWidth = (_props$nodeSize$ = (_props$nodeSize = props.nodeSize) === null || _props$nodeSize === void 0 ? void 0 : _props$nodeSize[0]) !== null && _props$nodeSize$ !== void 0 ? _props$nodeSize$ : 0;
38
+ const nodeHeight = (_props$nodeSize$2 = (_props$nodeSize2 = props.nodeSize) === null || _props$nodeSize2 === void 0 ? void 0 : _props$nodeSize2[1]) !== null && _props$nodeSize$2 !== void 0 ? _props$nodeSize$2 : 0;
39
+ const nodeWidthWithPadding = nodeWidth + styles.padding.adjacent;
40
+ const nodeHeightWithPadding = nodeHeight + styles.padding.above;
41
+ const nodeSize = [nodeWidthWithPadding, nodeHeightWithPadding];
42
+ const root = props.root;
43
+ const top = (_props$top = props.top) !== null && _props$top !== void 0 ? _props$top : 0;
44
+ const left = (_props$left = props.left) !== null && _props$left !== void 0 ? _props$left : 0;
45
+ const zoom = props === null || props === void 0 ? void 0 : props.zoom;
46
+ const cursor = zoom !== null && zoom !== void 0 && zoom.isDragging ? 'grabbing' : 'grab';
47
+ const children = props.children;
48
+ const renderDependencies = (_props$renderDependen = props.renderDependencies) !== null && _props$renderDependen !== void 0 ? _props$renderDependen : [];
49
+
50
+ /**
51
+ * If zoom is enabled, we need to apply the transform matrix to the SVG.
52
+ * If not, then use the static transform matrix provided in the styles prop.
53
+ * If no transform matrix is provided, then don't apply any transform.
54
+ */
55
+ const transformMatrix = (_styles$transformMatr = styles.transformMatrix) !== null && _styles$transformMatr !== void 0 ? _styles$transformMatr : {
56
+ scaleX: 1,
57
+ scaleY: 1,
58
+ skewX: 0,
59
+ skewY: 0,
60
+ translateX: document.body.clientWidth / 2,
61
+ translateY: 120
62
+ };
63
+ const transform = zoom ? zoom === null || zoom === void 0 ? void 0 : zoom.toString() : transformMatrix ? `matrix(${transformMatrix.scaleX}, ${transformMatrix.skewX}, ${transformMatrix.skewY}, ${transformMatrix.scaleY}, ${transformMatrix.translateX}, ${transformMatrix.translateY})` : undefined;
64
+ const edges = React.useMemo(() => {
65
+ return /*#__PURE__*/React.createElement(Tree, {
66
+ root: root,
67
+ top: top,
68
+ left: left,
69
+ nodeSize: nodeSize
70
+ }, tree => {
71
+ return /*#__PURE__*/React.createElement(React.Fragment, null, tree.links().map((link, linkIndex) => {
72
+ var _props$styles$lineAtt, _props$styles;
73
+ return /*#__PURE__*/React.createElement(LinkVerticalStep, _extends({
74
+ key: `link-${linkIndex}`,
75
+ data: link,
76
+ stroke: "var(--ds-border-accent-gray, #758195)",
77
+ strokeWidth: "1",
78
+ fill: "none",
79
+ opacity: 1,
80
+ percent: 0.5
81
+ }, (_props$styles$lineAtt = (_props$styles = props.styles) === null || _props$styles === void 0 ? void 0 : _props$styles.lineAttributes) !== null && _props$styles$lineAtt !== void 0 ? _props$styles$lineAtt : {}));
82
+ }));
83
+ });
84
+ // There are cases where the parent component will want to render the tree
85
+ // depending on certain props. so we need to pass the renderDependencies so the
86
+ // tree will re-render when the dependencies change.
87
+ // eslint-disable-next-line react-hooks/exhaustive-deps
88
+ }, [...renderDependencies, (_props$styles2 = props.styles) === null || _props$styles2 === void 0 ? void 0 : _props$styles2.lineAttributes]);
89
+ const nodes = React.useMemo(() => {
90
+ return /*#__PURE__*/React.createElement(Tree, {
91
+ root: root,
92
+ top: top,
93
+ left: left,
94
+ nodeSize: nodeSize
95
+ }, tree => {
96
+ const descendants = tree.descendants();
97
+ return /*#__PURE__*/React.createElement(React.Fragment, null, descendants.map((node, index) => {
98
+ const top = node.y - nodeHeight / 2;
99
+ const left = node.x - nodeWidth / 2;
100
+ return /*#__PURE__*/React.createElement("div", {
101
+ key: `tree-node-${index}`,
102
+ style: {
103
+ top: top,
104
+ left: left,
105
+ width: `${nodeWidth}px`,
106
+ height: `${nodeHeight}px`
107
+ },
108
+ className: ax([staticStyles.nodeWrapper])
109
+ }, children(node, isSuspending, startSuspending));
110
+ }));
111
+ });
112
+ // There are cases where the parent component will want to render the tree
113
+ // depending on certain props. so we need to pass the renderDependencies so the
114
+ // tree will re-render when the dependencies change.
115
+ // eslint-disable-next-line react-hooks/exhaustive-deps
116
+ }, [...renderDependencies, nodeHeight, isSuspending, nodeWidth, children]);
117
+ return /*#__PURE__*/React.createElement("div", {
118
+ style: {
119
+ height: `${containerHeight}px`,
120
+ width: `${containerWidth}px`
121
+ },
122
+ className: ax([staticStyles.hierarchyWrapper])
123
+ }, /*#__PURE__*/React.createElement("svg", {
124
+ width: containerWidth,
125
+ height: containerHeight,
126
+ style: {
127
+ cursor: `${cursor}`
128
+ },
129
+ ref: zoom ? zoom.containerRef : undefined,
130
+ className: ax([staticStyles.svg, zoom && ""])
131
+ }, zoom && /*#__PURE__*/React.createElement("rect", {
132
+ width: containerWidth,
133
+ height: containerHeight,
134
+ fill: "transparent",
135
+ onTouchStart: zoom.dragStart,
136
+ onTouchMove: zoom.dragMove,
137
+ onTouchEnd: zoom.dragEnd,
138
+ onMouseDown: zoom.dragStart,
139
+ onMouseMove: zoom.dragMove,
140
+ onMouseUp: zoom.dragEnd,
141
+ onMouseLeave: () => {
142
+ if (zoom.isDragging) {
143
+ zoom.dragEnd();
144
+ }
145
+ }
146
+ }), /*#__PURE__*/React.createElement(Group, {
147
+ transform: transform
148
+ }, edges)), /*#__PURE__*/React.createElement("div", {
149
+ style: {
150
+ transform: `${transform}`
151
+ },
152
+ className: ax([staticStyles.nodeGroupWrapper])
153
+ }, nodes));
154
+ };
@@ -0,0 +1 @@
1
+ export { CharlieHierarchy } from './charlie-hierarchy/charlie-hierarchy';
@@ -0,0 +1,5 @@
1
+ ._18m9ewfl{overflow-y:visible}
2
+ ._1reoewfl{overflow-x:visible}
3
+ ._1tktglyw{touch-action:none}
4
+ ._kqswh2mm{position:relative}
5
+ ._kqswstnw{position:absolute}
@@ -0,0 +1,159 @@
1
+ /* charlie-hierarchy.tsx generated by @compiled/babel-plugin v0.36.1 */
2
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
3
+ import _extends from "@babel/runtime/helpers/extends";
4
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
5
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
6
+ import "./charlie-hierarchy.compiled.css";
7
+ import { ax, ix } from "@compiled/react/runtime";
8
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
9
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
10
+ /**
11
+ * CharlieHierarchy is meant to be a generic reusable component for building SVG rendered trees.
12
+ * It is a wrapper around the visx Tree component that provides a more declarative API.
13
+ * https://airbnb.io/visx/docs/hierarchy#Tree
14
+ * Common use cases can be handled in the CharlieHierarchy component to allow for a quicker entry point to creating trees.
15
+ */
16
+
17
+ import React from 'react';
18
+ import { Group } from '@visx/group';
19
+ import { Tree } from '@visx/hierarchy';
20
+ import { LinkVerticalStep } from '@visx/shape';
21
+ var staticStyles = {
22
+ hierarchyWrapper: "_kqswh2mm",
23
+ nodeGroupWrapper: "_kqswstnw",
24
+ nodeWrapper: "_1reoewfl _18m9ewfl _kqswstnw",
25
+ svg: "_1reoewfl _18m9ewfl _kqswstnw",
26
+ zoom: "_1tktglyw"
27
+ };
28
+ export var CharlieHierarchy = function CharlieHierarchy(props) {
29
+ var _props$size$, _props$size, _props$size$2, _props$size2, _props$nodeSize$, _props$nodeSize, _props$nodeSize$2, _props$nodeSize2, _props$top, _props$left, _props$renderDependen, _styles$transformMatr, _props$styles2;
30
+ var _React$useTransition = React.useTransition(),
31
+ _React$useTransition2 = _slicedToArray(_React$useTransition, 2),
32
+ isSuspending = _React$useTransition2[0],
33
+ startSuspending = _React$useTransition2[1];
34
+ var styles = _objectSpread(_objectSpread({}, {
35
+ padding: {
36
+ above: 100,
37
+ adjacent: 30
38
+ }
39
+ }), props.styles);
40
+ var containerHeight = (_props$size$ = (_props$size = props.size) === null || _props$size === void 0 ? void 0 : _props$size[1]) !== null && _props$size$ !== void 0 ? _props$size$ : 0;
41
+ var containerWidth = (_props$size$2 = (_props$size2 = props.size) === null || _props$size2 === void 0 ? void 0 : _props$size2[0]) !== null && _props$size$2 !== void 0 ? _props$size$2 : 0;
42
+ var nodeWidth = (_props$nodeSize$ = (_props$nodeSize = props.nodeSize) === null || _props$nodeSize === void 0 ? void 0 : _props$nodeSize[0]) !== null && _props$nodeSize$ !== void 0 ? _props$nodeSize$ : 0;
43
+ var nodeHeight = (_props$nodeSize$2 = (_props$nodeSize2 = props.nodeSize) === null || _props$nodeSize2 === void 0 ? void 0 : _props$nodeSize2[1]) !== null && _props$nodeSize$2 !== void 0 ? _props$nodeSize$2 : 0;
44
+ var nodeWidthWithPadding = nodeWidth + styles.padding.adjacent;
45
+ var nodeHeightWithPadding = nodeHeight + styles.padding.above;
46
+ var nodeSize = [nodeWidthWithPadding, nodeHeightWithPadding];
47
+ var root = props.root;
48
+ var top = (_props$top = props.top) !== null && _props$top !== void 0 ? _props$top : 0;
49
+ var left = (_props$left = props.left) !== null && _props$left !== void 0 ? _props$left : 0;
50
+ var zoom = props === null || props === void 0 ? void 0 : props.zoom;
51
+ var cursor = zoom !== null && zoom !== void 0 && zoom.isDragging ? 'grabbing' : 'grab';
52
+ var children = props.children;
53
+ var renderDependencies = (_props$renderDependen = props.renderDependencies) !== null && _props$renderDependen !== void 0 ? _props$renderDependen : [];
54
+
55
+ /**
56
+ * If zoom is enabled, we need to apply the transform matrix to the SVG.
57
+ * If not, then use the static transform matrix provided in the styles prop.
58
+ * If no transform matrix is provided, then don't apply any transform.
59
+ */
60
+ var transformMatrix = (_styles$transformMatr = styles.transformMatrix) !== null && _styles$transformMatr !== void 0 ? _styles$transformMatr : {
61
+ scaleX: 1,
62
+ scaleY: 1,
63
+ skewX: 0,
64
+ skewY: 0,
65
+ translateX: document.body.clientWidth / 2,
66
+ translateY: 120
67
+ };
68
+ var transform = zoom ? zoom === null || zoom === void 0 ? void 0 : zoom.toString() : transformMatrix ? "matrix(".concat(transformMatrix.scaleX, ", ").concat(transformMatrix.skewX, ", ").concat(transformMatrix.skewY, ", ").concat(transformMatrix.scaleY, ", ").concat(transformMatrix.translateX, ", ").concat(transformMatrix.translateY, ")") : undefined;
69
+ var edges = React.useMemo(function () {
70
+ return /*#__PURE__*/React.createElement(Tree, {
71
+ root: root,
72
+ top: top,
73
+ left: left,
74
+ nodeSize: nodeSize
75
+ }, function (tree) {
76
+ return /*#__PURE__*/React.createElement(React.Fragment, null, tree.links().map(function (link, linkIndex) {
77
+ var _props$styles$lineAtt, _props$styles;
78
+ return /*#__PURE__*/React.createElement(LinkVerticalStep, _extends({
79
+ key: "link-".concat(linkIndex),
80
+ data: link,
81
+ stroke: "var(--ds-border-accent-gray, #758195)",
82
+ strokeWidth: "1",
83
+ fill: "none",
84
+ opacity: 1,
85
+ percent: 0.5
86
+ }, (_props$styles$lineAtt = (_props$styles = props.styles) === null || _props$styles === void 0 ? void 0 : _props$styles.lineAttributes) !== null && _props$styles$lineAtt !== void 0 ? _props$styles$lineAtt : {}));
87
+ }));
88
+ });
89
+ // There are cases where the parent component will want to render the tree
90
+ // depending on certain props. so we need to pass the renderDependencies so the
91
+ // tree will re-render when the dependencies change.
92
+ // eslint-disable-next-line react-hooks/exhaustive-deps
93
+ }, [].concat(_toConsumableArray(renderDependencies), [(_props$styles2 = props.styles) === null || _props$styles2 === void 0 ? void 0 : _props$styles2.lineAttributes]));
94
+ var nodes = React.useMemo(function () {
95
+ return /*#__PURE__*/React.createElement(Tree, {
96
+ root: root,
97
+ top: top,
98
+ left: left,
99
+ nodeSize: nodeSize
100
+ }, function (tree) {
101
+ var descendants = tree.descendants();
102
+ return /*#__PURE__*/React.createElement(React.Fragment, null, descendants.map(function (node, index) {
103
+ var top = node.y - nodeHeight / 2;
104
+ var left = node.x - nodeWidth / 2;
105
+ return /*#__PURE__*/React.createElement("div", {
106
+ key: "tree-node-".concat(index),
107
+ style: {
108
+ top: top,
109
+ left: left,
110
+ width: "".concat(nodeWidth, "px"),
111
+ height: "".concat(nodeHeight, "px")
112
+ },
113
+ className: ax([staticStyles.nodeWrapper])
114
+ }, children(node, isSuspending, startSuspending));
115
+ }));
116
+ });
117
+ // There are cases where the parent component will want to render the tree
118
+ // depending on certain props. so we need to pass the renderDependencies so the
119
+ // tree will re-render when the dependencies change.
120
+ // eslint-disable-next-line react-hooks/exhaustive-deps
121
+ }, [].concat(_toConsumableArray(renderDependencies), [nodeHeight, isSuspending, nodeWidth, children]));
122
+ return /*#__PURE__*/React.createElement("div", {
123
+ style: {
124
+ height: "".concat(containerHeight, "px"),
125
+ width: "".concat(containerWidth, "px")
126
+ },
127
+ className: ax([staticStyles.hierarchyWrapper])
128
+ }, /*#__PURE__*/React.createElement("svg", {
129
+ width: containerWidth,
130
+ height: containerHeight,
131
+ style: {
132
+ cursor: "".concat(cursor)
133
+ },
134
+ ref: zoom ? zoom.containerRef : undefined,
135
+ className: ax([staticStyles.svg, zoom && ""])
136
+ }, zoom && /*#__PURE__*/React.createElement("rect", {
137
+ width: containerWidth,
138
+ height: containerHeight,
139
+ fill: "transparent",
140
+ onTouchStart: zoom.dragStart,
141
+ onTouchMove: zoom.dragMove,
142
+ onTouchEnd: zoom.dragEnd,
143
+ onMouseDown: zoom.dragStart,
144
+ onMouseMove: zoom.dragMove,
145
+ onMouseUp: zoom.dragEnd,
146
+ onMouseLeave: function onMouseLeave() {
147
+ if (zoom.isDragging) {
148
+ zoom.dragEnd();
149
+ }
150
+ }
151
+ }), /*#__PURE__*/React.createElement(Group, {
152
+ transform: transform
153
+ }, edges)), /*#__PURE__*/React.createElement("div", {
154
+ style: {
155
+ transform: "".concat(transform)
156
+ },
157
+ className: ax([staticStyles.nodeGroupWrapper])
158
+ }, nodes));
159
+ };
@@ -0,0 +1 @@
1
+ export { CharlieHierarchy } from './charlie-hierarchy/charlie-hierarchy';
@@ -0,0 +1,65 @@
1
+ /**
2
+ * CharlieHierarchy is meant to be a generic reusable component for building SVG rendered trees.
3
+ * It is a wrapper around the visx Tree component that provides a more declarative API.
4
+ * https://airbnb.io/visx/docs/hierarchy#Tree
5
+ * Common use cases can be handled in the CharlieHierarchy component to allow for a quicker entry point to creating trees.
6
+ */
7
+ /**
8
+ * @jsxRuntime classic
9
+ * @jsx jsx
10
+ * @jsxFrag React.Fragment
11
+ */
12
+ import React from 'react';
13
+ import { type TreeProps } from '@visx/hierarchy/lib/hierarchies/Tree';
14
+ import { type HierarchyPointNode } from '@visx/hierarchy/lib/types';
15
+ import { type ProvidedZoom, type TransformMatrix } from '@visx/zoom/lib/types';
16
+ export interface CharlieHierarchyProps<Datum> extends Omit<TreeProps<Datum>, 'children'> {
17
+ /**
18
+ * Children gets called for each node when the tree is being generated.
19
+ * This is where you can render your custom node components.
20
+ */
21
+ children: (node: HierarchyPointNode<Datum>, isSuspending: boolean, startSuspending: React.TransitionStartFunction) => React.ReactNode;
22
+ /**
23
+ * zoom controller that is passed to the space tree component to enable zooming and panning functionality.
24
+ * https://github.com/airbnb/visx/blob/master/packages/visx-zoom/src/types.ts#L49
25
+ *
26
+ * This can be passed to the space tree from the parent zoom component.
27
+ * https://airbnb.io/visx/zoom-i
28
+ *
29
+ * <Zoom<SVGSVGElement>
30
+ * {(zoom) => (
31
+ * <CharlieHierarchy zoom={zoom} ... />
32
+ * )}
33
+ * <Zoom>
34
+ */
35
+ zoom?: ProvidedZoom<SVGSVGElement> & {
36
+ initialTransformMatrix: TransformMatrix;
37
+ transformMatrix: TransformMatrix;
38
+ isDragging: boolean;
39
+ };
40
+ styles?: {
41
+ padding?: {
42
+ above: number;
43
+ adjacent: number;
44
+ };
45
+ lineAttributes?: Omit<React.SVGAttributes<unknown>, 'className' | 'innerRef' | 'data' | 'path' | 'percent' | 'x' | 'y' | 'source' | 'target' | 'children'>;
46
+ /**
47
+ * A transform matrix that can be applied to the tree.
48
+ * If you are using zoom, this will be overridden by the zoom transform matrix.
49
+ */
50
+ transformMatrix?: {
51
+ scaleX: number;
52
+ scaleY: number;
53
+ skewX: number;
54
+ skewY: number;
55
+ translateX: number;
56
+ translateY: number;
57
+ };
58
+ };
59
+ /**
60
+ * Rendering the tree can be expensive, so we provide a way to pass in dependencies to the render function.
61
+ * Pass any dependencies that on change should trigger a re-render of the tree.
62
+ */
63
+ renderDependencies?: React.DependencyList;
64
+ }
65
+ export declare const CharlieHierarchy: <Datum>(props: CharlieHierarchyProps<Datum>) => JSX.Element;
@@ -0,0 +1 @@
1
+ export { CharlieHierarchy, type CharlieHierarchyProps } from './charlie-hierarchy/charlie-hierarchy';
@@ -0,0 +1,65 @@
1
+ /**
2
+ * CharlieHierarchy is meant to be a generic reusable component for building SVG rendered trees.
3
+ * It is a wrapper around the visx Tree component that provides a more declarative API.
4
+ * https://airbnb.io/visx/docs/hierarchy#Tree
5
+ * Common use cases can be handled in the CharlieHierarchy component to allow for a quicker entry point to creating trees.
6
+ */
7
+ /**
8
+ * @jsxRuntime classic
9
+ * @jsx jsx
10
+ * @jsxFrag React.Fragment
11
+ */
12
+ import React from 'react';
13
+ import { type TreeProps } from '@visx/hierarchy/lib/hierarchies/Tree';
14
+ import { type HierarchyPointNode } from '@visx/hierarchy/lib/types';
15
+ import { type ProvidedZoom, type TransformMatrix } from '@visx/zoom/lib/types';
16
+ export interface CharlieHierarchyProps<Datum> extends Omit<TreeProps<Datum>, 'children'> {
17
+ /**
18
+ * Children gets called for each node when the tree is being generated.
19
+ * This is where you can render your custom node components.
20
+ */
21
+ children: (node: HierarchyPointNode<Datum>, isSuspending: boolean, startSuspending: React.TransitionStartFunction) => React.ReactNode;
22
+ /**
23
+ * zoom controller that is passed to the space tree component to enable zooming and panning functionality.
24
+ * https://github.com/airbnb/visx/blob/master/packages/visx-zoom/src/types.ts#L49
25
+ *
26
+ * This can be passed to the space tree from the parent zoom component.
27
+ * https://airbnb.io/visx/zoom-i
28
+ *
29
+ * <Zoom<SVGSVGElement>
30
+ * {(zoom) => (
31
+ * <CharlieHierarchy zoom={zoom} ... />
32
+ * )}
33
+ * <Zoom>
34
+ */
35
+ zoom?: ProvidedZoom<SVGSVGElement> & {
36
+ initialTransformMatrix: TransformMatrix;
37
+ transformMatrix: TransformMatrix;
38
+ isDragging: boolean;
39
+ };
40
+ styles?: {
41
+ padding?: {
42
+ above: number;
43
+ adjacent: number;
44
+ };
45
+ lineAttributes?: Omit<React.SVGAttributes<unknown>, 'className' | 'innerRef' | 'data' | 'path' | 'percent' | 'x' | 'y' | 'source' | 'target' | 'children'>;
46
+ /**
47
+ * A transform matrix that can be applied to the tree.
48
+ * If you are using zoom, this will be overridden by the zoom transform matrix.
49
+ */
50
+ transformMatrix?: {
51
+ scaleX: number;
52
+ scaleY: number;
53
+ skewX: number;
54
+ skewY: number;
55
+ translateX: number;
56
+ translateY: number;
57
+ };
58
+ };
59
+ /**
60
+ * Rendering the tree can be expensive, so we provide a way to pass in dependencies to the render function.
61
+ * Pass any dependencies that on change should trigger a re-render of the tree.
62
+ */
63
+ renderDependencies?: React.DependencyList;
64
+ }
65
+ export declare const CharlieHierarchy: <Datum>(props: CharlieHierarchyProps<Datum>) => JSX.Element;
@@ -0,0 +1 @@
1
+ export { CharlieHierarchy, type CharlieHierarchyProps } from './charlie-hierarchy/charlie-hierarchy';
package/package.json ADDED
@@ -0,0 +1,104 @@
1
+ {
2
+ "atlassian": {
3
+ "team": "Technology Innovation",
4
+ "runReact18": true,
5
+ "website": {
6
+ "name": "CharlieHierarchy",
7
+ "category": "Layout and structure"
8
+ }
9
+ },
10
+ "repository": "https://stash.atlassian.com/projects/ATLASSIAN/repos/atlassian-frontend-monorepo",
11
+ "main": "dist/cjs/index.js",
12
+ "module": "dist/esm/index.js",
13
+ "module:es2019": "dist/es2019/index.js",
14
+ "types": "dist/types/index.d.ts",
15
+ "typesVersions": {
16
+ ">=4.5 <5.4": {
17
+ "*": [
18
+ "dist/types-ts4.5/*",
19
+ "dist/types-ts4.5/index.d.ts"
20
+ ]
21
+ }
22
+ },
23
+ "sideEffects": [
24
+ "*.compiled.css"
25
+ ],
26
+ "atlaskit:src": "src/index.ts",
27
+ "af:exports": {
28
+ ".": "./src/index.ts"
29
+ },
30
+ "dependencies": {
31
+ "@atlaskit/css": "^0.10.0",
32
+ "@atlaskit/primitives": "^14.8.0",
33
+ "@atlaskit/tokens": "^4.9.0",
34
+ "@babel/runtime": "^7.0.0",
35
+ "@compiled/react": "^0.18.3",
36
+ "@visx/group": "^1.7.0",
37
+ "@visx/hierarchy": "^1.7.0",
38
+ "@visx/shape": "^1.7.0",
39
+ "@visx/zoom": "^2.10.0"
40
+ },
41
+ "peerDependencies": {
42
+ "react": "^18.2.0"
43
+ },
44
+ "devDependencies": {
45
+ "@af/integration-testing": "workspace:^",
46
+ "@af/visual-regression": "workspace:^",
47
+ "@atlaskit/ssr": "workspace:^",
48
+ "@atlaskit/visual-regression": "workspace:^",
49
+ "@testing-library/react": "^13.4.0",
50
+ "react-dom": "^18.2.0",
51
+ "typescript": "~5.4.2"
52
+ },
53
+ "techstack": {
54
+ "@atlassian/frontend": {
55
+ "code-structure": [
56
+ "tangerine-next"
57
+ ],
58
+ "import-structure": [
59
+ "atlassian-conventions"
60
+ ],
61
+ "circular-dependencies": [
62
+ "file-and-folder-level"
63
+ ]
64
+ },
65
+ "@repo/internal": {
66
+ "dom-events": "use-bind-event-listener",
67
+ "analytics": [
68
+ "analytics-next"
69
+ ],
70
+ "design-tokens": [
71
+ "color"
72
+ ],
73
+ "theming": [
74
+ "react-context"
75
+ ],
76
+ "ui-components": [
77
+ "lite-mode"
78
+ ],
79
+ "deprecation": [
80
+ "no-deprecated-imports"
81
+ ],
82
+ "styling": [
83
+ "static",
84
+ "compiled"
85
+ ],
86
+ "imports": [
87
+ "import-no-extraneous-disable-for-examples-and-docs"
88
+ ]
89
+ }
90
+ },
91
+ "techstackIgnore": {
92
+ "stricter": [
93
+ "@atlassian/tangerine/project-structure"
94
+ ]
95
+ },
96
+ "name": "@atlaskit/charlie-hierarchy",
97
+ "version": "0.0.0",
98
+ "description": "Add a description here.",
99
+ "author": "Atlassian Pty Ltd",
100
+ "license": "Apache-2.0",
101
+ "publishConfig": {
102
+ "registry": "https://registry.npmjs.org/"
103
+ }
104
+ }