@geneui/components 3.0.0-next-e06ec94-05082025 → 3.0.0-next-67f77e7-11082025
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/Menu.js +49 -19
- package/Navigation.js +101 -70
- package/components/molecules/Menu/Menu.d.ts +5 -5
- package/components/molecules/Menu/MenuItem.d.ts +8 -1
- package/components/molecules/Navigation/Navigation.d.ts +12 -1
- package/components/molecules/Navigation/NavigationItem.d.ts +4 -2
- package/components/molecules/Navigation/NavigattionColItem.d.ts +2 -0
- package/package.json +1 -1
package/Menu.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React__default, { createContext, useState, useRef, useContext, useEffect, useMemo, Children, cloneElement } from 'react';
|
|
1
|
+
import React__default, { createContext, useState, useRef, useContext, useEffect, useMemo, Children, cloneElement, isValidElement } from 'react';
|
|
2
2
|
import { c as classNames } from './index-ce02421b.js';
|
|
3
3
|
import Loader from './Loader.js';
|
|
4
4
|
import { P as Popover, a as PopoverBody } from './PopoverBody-7437f3ac.js';
|
|
@@ -60,12 +60,12 @@ const findPathOfSelected = (menu, path = []) => {
|
|
|
60
60
|
const MENU_GAP_FROM_TARGET = 4;
|
|
61
61
|
const cloneChildrenRecursive = (children, paths, props = {}, pathID = "") => {
|
|
62
62
|
return Children.map(children, (child, i) => {
|
|
63
|
-
var _a, _b
|
|
63
|
+
var _a, _b;
|
|
64
64
|
const generatedId = pathID ? `${pathID}_${i}` : `${i}`;
|
|
65
65
|
return cloneElement(child, Object.assign(Object.assign({}, props), { generatedId,
|
|
66
|
-
paths }),
|
|
67
|
-
? cloneChildrenRecursive((
|
|
68
|
-
: (
|
|
66
|
+
paths }), child.props.children && typeof child.props.children !== "string"
|
|
67
|
+
? cloneChildrenRecursive((_a = child.props) === null || _a === void 0 ? void 0 : _a.children, paths, props, generatedId)
|
|
68
|
+
: (_b = child.props) === null || _b === void 0 ? void 0 : _b.children);
|
|
69
69
|
});
|
|
70
70
|
};
|
|
71
71
|
const MenuContext = createContext({});
|
|
@@ -127,7 +127,7 @@ const Menu = ({ onChange, children, loading, loadingText, swappable, setPropsFor
|
|
|
127
127
|
if (onOpenChange) {
|
|
128
128
|
onOpenChange(isOpenState);
|
|
129
129
|
}
|
|
130
|
-
}, [isOpenState]);
|
|
130
|
+
}, [isOpenState, onOpenChange]);
|
|
131
131
|
const onChangeHandler = ({ generatedId, isBack, closeMenu, item }) => {
|
|
132
132
|
if (swappable || isMobileBreakpoint)
|
|
133
133
|
setOpenSelectedPathState(false);
|
|
@@ -142,7 +142,7 @@ const Menu = ({ onChange, children, loading, loadingText, swappable, setPropsFor
|
|
|
142
142
|
else {
|
|
143
143
|
setPaths(currentPath);
|
|
144
144
|
}
|
|
145
|
-
if (closeMenu) {
|
|
145
|
+
if (closeMenu && onChange) {
|
|
146
146
|
onChange(Object.assign(Object.assign({}, item), { title: typeof (item === null || item === void 0 ? void 0 : item.children) === "string" ? item === null || item === void 0 ? void 0 : item.children : item === null || item === void 0 ? void 0 : item.title }));
|
|
147
147
|
}
|
|
148
148
|
};
|
|
@@ -157,7 +157,7 @@ const Menu = ({ onChange, children, loading, loadingText, swappable, setPropsFor
|
|
|
157
157
|
relativeRefsSetter,
|
|
158
158
|
openSelectedPath: openSelectedPathState,
|
|
159
159
|
size: size
|
|
160
|
-
}), [onChangeHandler, swappable, size, isMobileBreakpoint, relativeRefsSetter,
|
|
160
|
+
}), [onChangeHandler, swappable, size, isMobileBreakpoint, relativeRefsSetter, openSelectedPathState]);
|
|
161
161
|
const clonedChildren = cloneChildrenRecursive(children, paths);
|
|
162
162
|
const onScrollHandler = () => {
|
|
163
163
|
if (isMobileBreakpoint)
|
|
@@ -242,7 +242,7 @@ const MenuItemButton = ({ type, onItemClickHandler, disabled, children, danger,
|
|
|
242
242
|
};
|
|
243
243
|
|
|
244
244
|
const MenuItem = (props) => {
|
|
245
|
-
const { children, title, activeElement, selected, IconBefore, IconAfter, danger, disabled, id, divider, ComponentRender, emptyText = "No data to show", paths, generatedId, loading, loadingText } = props;
|
|
245
|
+
const { children, title, activeElement, selected, IconBefore, IconAfter, danger, disabled, id, divider, ComponentRender, emptyText = "No data to show", paths, generatedId, loading, loadingText, render } = props;
|
|
246
246
|
const [propsForPopover, setPropsForPopover] = useState({});
|
|
247
247
|
const parentRef = useRef(null);
|
|
248
248
|
const { onChangeHandler, swappable, relativeRefsSetter, size, openSelectedPath } = useContext(MenuContext);
|
|
@@ -267,7 +267,14 @@ const MenuItem = (props) => {
|
|
|
267
267
|
});
|
|
268
268
|
const onItemClickHandler = (isBack) => {
|
|
269
269
|
if (onChangeHandler && generatedId) {
|
|
270
|
-
|
|
270
|
+
const shouldCloseMenu = !!render || typeof children === "string";
|
|
271
|
+
onChangeHandler({
|
|
272
|
+
generatedId,
|
|
273
|
+
id,
|
|
274
|
+
isBack,
|
|
275
|
+
closeMenu: shouldCloseMenu,
|
|
276
|
+
item: props
|
|
277
|
+
});
|
|
271
278
|
}
|
|
272
279
|
};
|
|
273
280
|
useEffect(() => {
|
|
@@ -314,28 +321,51 @@ const MenuItem = (props) => {
|
|
|
314
321
|
}
|
|
315
322
|
return React__default.createElement("div", { className: "menu__content" }, children);
|
|
316
323
|
}, [children, emptyText, loading, loadingText, swappable, isActiveSwappableContent]);
|
|
324
|
+
const renderMenuItem = (type) => {
|
|
325
|
+
if (render && type === "simple") {
|
|
326
|
+
const renderedElement = render({ id, title: children });
|
|
327
|
+
if (isValidElement(renderedElement)) {
|
|
328
|
+
const originalOnClick = renderedElement.props
|
|
329
|
+
.onClick;
|
|
330
|
+
const propsToApply = {
|
|
331
|
+
className: classNames("menu__item", renderedElement.props.className, {
|
|
332
|
+
menu__item_danger: danger,
|
|
333
|
+
menu__item_disabled: disabled,
|
|
334
|
+
menu__item_selected: selected,
|
|
335
|
+
menu__item_icon_after: !!IconAfter,
|
|
336
|
+
menu__item_icon_before: !!IconBefore
|
|
337
|
+
}),
|
|
338
|
+
onClick: (event) => {
|
|
339
|
+
originalOnClick === null || originalOnClick === void 0 ? void 0 : originalOnClick(event);
|
|
340
|
+
onItemClickHandler(false);
|
|
341
|
+
},
|
|
342
|
+
disabled
|
|
343
|
+
};
|
|
344
|
+
return cloneElement(renderedElement, propsToApply, children);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
if (type === "custom" && CustomElement) {
|
|
348
|
+
return CustomElement;
|
|
349
|
+
}
|
|
350
|
+
return (React__default.createElement(MenuItemButton, { type: type, onItemClickHandler: onItemClickHandler, title: title, IconBefore: IconBefore, IconAfter: IconAfter, disabled: disabled, danger: danger, propsForPopover: propsForPopover, active: popoverOpenState, divider: divider, selected: selected }, children));
|
|
351
|
+
};
|
|
317
352
|
return swappable ? (React__default.createElement(React__default.Fragment, null, typeof children !== "string" ? (React__default.createElement(React__default.Fragment, null,
|
|
318
|
-
isActiveSwappableContent && !popoverOpenState && (
|
|
353
|
+
isActiveSwappableContent && !popoverOpenState && renderMenuItem("parent"),
|
|
319
354
|
React__default.createElement("div", { className: classNames("menu__list", {
|
|
320
355
|
menu__list_current: popoverOpenState,
|
|
321
356
|
menu__list_hidden: !popoverOpenState
|
|
322
357
|
}) },
|
|
323
358
|
isActiveSwappableContent && (React__default.createElement("div", { className: "menu__header" },
|
|
324
359
|
React__default.createElement(MenuItemButton, { type: "header", onItemClickHandler: onItemClickHandler, title: title }))),
|
|
325
|
-
menuContent))) : (
|
|
326
|
-
|
|
327
|
-
isActiveSwappableContent &&
|
|
328
|
-
(CustomElement || (React__default.createElement(MenuItemButton, { type: "simple", onItemClickHandler: onItemClickHandler, danger: danger, selected: selected, disabled: disabled, IconBefore: IconBefore, IconAfter: IconAfter, divider: divider }, children)))))) : (React__default.createElement(React__default.Fragment, null, typeof children !== "string" ? (React__default.createElement(React__default.Fragment, null,
|
|
329
|
-
React__default.createElement(MenuItemButton, { type: "parent", onItemClickHandler: onItemClickHandler, title: title, IconBefore: IconBefore, IconAfter: IconAfter, disabled: disabled, danger: danger, propsForPopover: propsForPopover, active: popoverOpenState, divider: divider }),
|
|
360
|
+
menuContent))) : (isActiveSwappableContent && renderMenuItem(ComponentRender ? "custom" : "simple")))) : (React__default.createElement(React__default.Fragment, null, typeof children !== "string" ? (React__default.createElement(React__default.Fragment, null,
|
|
361
|
+
renderMenuItem("parent"),
|
|
330
362
|
React__default.createElement(Popover, { setProps: setPropsForPopover, size: popoverSizeMapping[size], position: isRTLMode ? "left-top" : "right-top", withArrow: false, margin: 10, open: popoverOpenState, ref: popoverFloatingRef },
|
|
331
363
|
React__default.createElement(PopoverBody, { withPadding: false, className: `menu__body menu__body_size menu__body_size_${size}`, withScrollbar: false },
|
|
332
364
|
React__default.createElement("div", { ref: parentRef, className: classNames("menu__list", {
|
|
333
365
|
menu__list_current: activeElement,
|
|
334
366
|
menu__item_disabled: disabled
|
|
335
367
|
}) },
|
|
336
|
-
React__default.createElement(Scrollbar, { className: "menu__scrollbar", onScroll: onScrollHandler, scrollToTop: activeElementPosition, scrollBehaviorSmooth: false }, menuContent)))))) : (
|
|
337
|
-
// Simple menu item
|
|
338
|
-
CustomElement || (React__default.createElement(MenuItemButton, { type: "simple", onItemClickHandler: onItemClickHandler, danger: danger, selected: selected, disabled: disabled, IconBefore: IconBefore, IconAfter: IconAfter, divider: divider }, children)))));
|
|
368
|
+
React__default.createElement(Scrollbar, { className: "menu__scrollbar", onScroll: onScrollHandler, scrollToTop: activeElementPosition, scrollBehaviorSmooth: false }, menuContent)))))) : (renderMenuItem(ComponentRender ? "custom" : "simple"))));
|
|
339
369
|
};
|
|
340
370
|
|
|
341
371
|
export { Menu, MenuItem };
|
package/Navigation.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React__default, { useRef, useEffect,
|
|
1
|
+
import React__default, { useState, useRef, useEffect, isValidElement, cloneElement, useContext, Fragment } from 'react';
|
|
2
2
|
import { c as classNames } from './index-ce02421b.js';
|
|
3
3
|
import { _ as _objectWithoutProperties, a as _extends } from './ActivityRecent-b88e2ba8.js';
|
|
4
4
|
import { S as SvgThreeDotsHorizontal } from './ThreeDotsHorizontal-479c2b4b.js';
|
|
@@ -77,8 +77,8 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
|
|
|
77
77
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
78
78
|
};
|
|
79
79
|
|
|
80
|
-
const NavigationItem = ({ title, children, onClick, disabled, selected, depth, Icon, path }) => {
|
|
81
|
-
const [isNavItemOpen, setIsNavItemOpen] =
|
|
80
|
+
const NavigationItem = ({ title, children, onClick, disabled, selected, depth, Icon, path, render }) => {
|
|
81
|
+
const [isNavItemOpen, setIsNavItemOpen] = useState(false);
|
|
82
82
|
const textRef = useRef(null);
|
|
83
83
|
const isTruncated = useEllipsisDetection(textRef, [title]);
|
|
84
84
|
const onClickHandler = () => {
|
|
@@ -92,23 +92,41 @@ const NavigationItem = ({ title, children, onClick, disabled, selected, depth, I
|
|
|
92
92
|
return;
|
|
93
93
|
setIsNavItemOpen(selected);
|
|
94
94
|
}, [title, selected]);
|
|
95
|
+
const itemContent = (React__default.createElement(React__default.Fragment, null,
|
|
96
|
+
Icon && React__default.createElement(Icon, { className: "navigationItem__icon", size: 20 }),
|
|
97
|
+
React__default.createElement(Tooltip, { text: title, isVisible: isTruncated },
|
|
98
|
+
React__default.createElement(Text, { as: "span", variant: "labelMediumMedium", className: "menu__title ellipsis-text", ref: textRef }, title)),
|
|
99
|
+
children && (React__default.createElement(SvgChevronRight, { className: classNames("navigationItem__chevron", {
|
|
100
|
+
navigationItem__chevron_open: isNavItemOpen
|
|
101
|
+
}), size: 20 }))));
|
|
102
|
+
const propsToApply = {
|
|
103
|
+
"aria-expanded": children ? isNavItemOpen : undefined,
|
|
104
|
+
disabled,
|
|
105
|
+
className: classNames("navigationItem__button", `navigationItem__button_shift_${depth}`, {
|
|
106
|
+
navigationItem__button_disabled: disabled,
|
|
107
|
+
navigationItem__button_selected: selected,
|
|
108
|
+
navigationItem__button_pointer_none: selected && !children,
|
|
109
|
+
navigationItem__button_selected_noChildren: !children && selected,
|
|
110
|
+
navigationItem__button_render: render && path
|
|
111
|
+
}),
|
|
112
|
+
onClick: onClickHandler
|
|
113
|
+
};
|
|
114
|
+
const linkData = { path, title, isActive: selected, hasChildren: !!children, isDisabled: disabled };
|
|
115
|
+
const interactiveElement = (() => {
|
|
116
|
+
if (render && path) {
|
|
117
|
+
const renderedElement = render(linkData);
|
|
118
|
+
if (isValidElement(renderedElement)) {
|
|
119
|
+
return cloneElement(renderedElement, Object.assign({}, propsToApply), itemContent);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return (React__default.createElement("button", Object.assign({ type: "button" }, propsToApply), itemContent));
|
|
123
|
+
})();
|
|
95
124
|
return (React__default.createElement("div", { className: "navigationItem" },
|
|
96
|
-
|
|
97
|
-
navigationItem__button_disabled: disabled,
|
|
98
|
-
navigationItem__button_selected: selected,
|
|
99
|
-
navigationItem__button_pointer_none: selected && !children,
|
|
100
|
-
navigationItem__button_selected_noChildren: !children && selected
|
|
101
|
-
}), onClick: onClickHandler },
|
|
102
|
-
Icon && React__default.createElement(Icon, { className: "navigationItem__icon", size: 20 }),
|
|
103
|
-
React__default.createElement(Tooltip, { text: title, isVisible: isTruncated },
|
|
104
|
-
React__default.createElement(Text, { as: "span", variant: "labelMediumMedium", className: "menu__title ellipsis-text", ref: textRef }, title)),
|
|
105
|
-
children && (React__default.createElement(SvgChevronRight, { className: classNames("navigationItem__chevron", {
|
|
106
|
-
navigationItem__chevron_open: isNavItemOpen
|
|
107
|
-
}), size: 20 }))),
|
|
125
|
+
interactiveElement,
|
|
108
126
|
isNavItemOpen && children));
|
|
109
127
|
};
|
|
110
128
|
|
|
111
|
-
const NavigationColItem = ({ Icon, selected, disabled, title, onClick, index, onMouseEnter, propsForPopover = {}, opened, path, isVisible, hasChildren, currentSelected }) => {
|
|
129
|
+
const NavigationColItem = ({ Icon, selected, disabled, title, onClick, index, onMouseEnter, propsForPopover = {}, opened, path, isVisible, hasChildren, currentSelected, render }) => {
|
|
112
130
|
const textRef = useRef(null);
|
|
113
131
|
const isTruncated = useEllipsisDetection(textRef, [title]);
|
|
114
132
|
const onClickHandler = (activeIndex) => {
|
|
@@ -121,20 +139,39 @@ const NavigationColItem = ({ Icon, selected, disabled, title, onClick, index, on
|
|
|
121
139
|
onMouseEnter(activeIndex);
|
|
122
140
|
}
|
|
123
141
|
};
|
|
142
|
+
const propsToApply = Object.assign(Object.assign({}, propsForPopover), { "aria-label": title, disabled: disabled || !isVisible, className: classNames("navigation__iconButton", {
|
|
143
|
+
navigation__iconButton_selected: selected,
|
|
144
|
+
navigation__iconButton_currentSelected: currentSelected && !selected && opened,
|
|
145
|
+
navigation__iconButton_pointer_none: selected && !hasChildren,
|
|
146
|
+
navigation__iconButton_disabled: disabled
|
|
147
|
+
}), onClick: () => onClickHandler(index || 0), onMouseEnter: () => onMouseEnterHandler(index || 0) });
|
|
148
|
+
const linkData = {
|
|
149
|
+
path,
|
|
150
|
+
title,
|
|
151
|
+
Icon,
|
|
152
|
+
isActive: selected,
|
|
153
|
+
hasChildren,
|
|
154
|
+
isDisabled: disabled
|
|
155
|
+
};
|
|
156
|
+
const interactiveElement = (() => {
|
|
157
|
+
if (render && path) {
|
|
158
|
+
const renderedElement = render(linkData);
|
|
159
|
+
if (isValidElement(renderedElement)) {
|
|
160
|
+
return cloneElement(renderedElement, Object.assign({}, propsToApply), Icon && React__default.createElement(Icon, null));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return (React__default.createElement("button", Object.assign({ type: "button" }, propsToApply), Icon && React__default.createElement(Icon, null)));
|
|
164
|
+
})();
|
|
124
165
|
return (React__default.createElement("div", { className: "navigation__listItem" },
|
|
125
|
-
|
|
126
|
-
navigation__iconButton_selected: selected,
|
|
127
|
-
navigation__iconButton_currentSelected: currentSelected && !selected && opened,
|
|
128
|
-
navigation__iconButton_pointer_none: selected && !hasChildren,
|
|
129
|
-
navigation__iconButton_disabled: disabled
|
|
130
|
-
}), onClick: () => onClickHandler(index), onMouseEnter: () => onMouseEnterHandler(index) }, propsForPopover), Icon && React__default.createElement(Icon, null)),
|
|
166
|
+
interactiveElement,
|
|
131
167
|
title && (React__default.createElement(Tooltip, { text: title, isVisible: isTruncated },
|
|
132
168
|
React__default.createElement(Text, { as: "p", variant: "captionMediumMedium", className: "navigation__listItemText ellipsis-text", ref: textRef }, title)))));
|
|
133
169
|
};
|
|
134
170
|
|
|
135
|
-
var css_248z = ".navigation{display:flex;height:100%;width:100%}.navigation__list{display:flex;height:100%;width:var(--guit-sem-dimension-width-3xlarge)}.navigation__listWrapper{align-items:center;border-inline-end:var(--guit-ref-border-width-thin) var(--guit-ref-border-style-solid) var(--guit-sem-color-border-neutral-2);display:flex;flex-direction:column;overflow:hidden;padding:var(--guit-ref-spacing-xsmall) var(--guit-ref-spacing-xsmall) var(--guit-ref-spacing-2xlarge) var(--guit-ref-spacing-xsmall);width:100%}.navigation__listWrapper>.navigation__listItem{margin-block:var(--guit-ref-spacing-xsmall)}.navigation__listItems{display:flex;flex-flow:column wrap;gap:var(--guit-ref-spacing-xsmall);max-width:var(--guit-sem-dimension-height-xlarge);min-height:0}.navigation__listItem{align-items:center;display:flex;flex-direction:column;width:100%}.navigation__addButton{align-items:center;display:flex;flex:0 0 auto;flex-direction:column;height:var(--guit-sem-dimension-height-large);margin-top:auto;width:var(--guit-sem-dimension-width-large)}.navigation__listItemText{color:var(--guit-sem-color-foreground-neutral-1);max-width:100%;-webkit-user-select:none;user-select:none}.navigation__iconButton{border-radius:var(--guit-ref-radius-3xsmall);height:var(--guit-sem-dimension-height-large);padding:var(--guit-ref-spacing-xsmall);width:var(--guit-sem-dimension-width-large)}.navigation__iconButton_selected{background-color:var(--guit-sem-color-background-selected-2);color:var(--guit-sem-color-foreground-inverse)}.navigation__iconButton_currentSelected{background-color:var(--guit-sem-color-background-neutral-1-pressed)}.navigation__iconButton_disabled{background-color:var(--guit-sem-color-background-neutral-1);pointer-events:none}.navigation__iconButton_disabled,.navigation__iconButton_disabled+.navigation__listItemText{color:var(--guit-sem-color-foreground-disabled)}.navigation__iconButton_pointer_none{pointer-events:none}.navigation__iconButton:not(.navigation__iconButton_selected,.navigation__iconButton_disabled){color:var(--guit-sem-color-foreground-neutral-2)}.navigation__iconButton:not(.navigation__iconButton_selected,.navigation__iconButton_disabled):hover{background-color:var(--guit-sem-color-background-neutral-1-hover)}.navigation__iconButton:not(.navigation__iconButton_selected,.navigation__iconButton_disabled):active{background-color:var(--guit-sem-color-background-neutral-1-pressed)}.navigation__divider{flex:0 0 auto}.navigation__menu{border-inline-end:var(--guit-ref-border-width-thin) var(--guit-ref-border-style-solid) var(--guit-sem-color-border-neutral-2);display:flex;height:100%;width:20rem}.navigation__menu_wrapper{height:100%;padding:var(--guit-ref-spacing-3xsmall) var(--guit-ref-spacing-xsmall)}.navigationItem,.navigation__menu_wrapper{display:flex;flex-direction:column;gap:var(--guit-ref-spacing-3xsmall);width:100%}.navigationItem__button{border-radius:var(--guit-ref-radius-3xsmall);display:flex;gap:var(--guit-ref-spacing-xsmall);padding:var(--guit-ref-spacing-xsmall) var(--guit-ref-spacing-xsmall) var(--guit-ref-spacing-xsmall) var(--guit-ref-spacing-medium);width:100%}.navigationItem__button:hover{background-color:var(--guit-sem-color-background-neutral-1-hover)}.navigationItem__button:active{background-color:var(--guit-sem-color-background-neutral-1-pressed)}.navigationItem__button_selected{color:var(--guit-sem-color-foreground-selected)}.navigationItem__button_selected_noChildren{background:var(--guit-sem-color-background-neutral-3);color:var(--guit-sem-color-foreground-accent-blue)}.navigationItem__button_pointer_none{pointer-events:none}.navigationItem__button_disabled{background-color:var(--guit-sem-color-background-neutral-1);color:var(--guit-sem-color-foreground-disabled);pointer-events:none}.navigationItem__button_shift_1{padding-inline-start:var(--guit-ref-spacing-5xlarge)}.navigationItem__button_shift_2{padding-inline-start:var(--guit-ref-spacing-8xlarge)}.navigationItem__button_shift_3{padding-inline-start:var(--guit-ref-spacing-9xlarge)}.navigationItem__button_shift_4{padding-inline-start:var(--guit-ref-spacing-10xlarge)}.navigationItem__chevron{margin-left:auto}.navigationItem__chevron_open{transform:rotate(90deg)}";
|
|
171
|
+
var css_248z = ".navigation{display:flex;height:100%;width:100%}.navigation__list{display:flex;height:100%;width:var(--guit-sem-dimension-width-3xlarge)}.navigation__listWrapper{align-items:center;border-inline-end:var(--guit-ref-border-width-thin) var(--guit-ref-border-style-solid) var(--guit-sem-color-border-neutral-2);display:flex;flex-direction:column;overflow:hidden;padding:var(--guit-ref-spacing-xsmall) var(--guit-ref-spacing-xsmall) var(--guit-ref-spacing-2xlarge) var(--guit-ref-spacing-xsmall);width:100%}.navigation__listWrapper>.navigation__listItem{margin-block:var(--guit-ref-spacing-xsmall)}.navigation__listItems{display:flex;flex-flow:column wrap;gap:var(--guit-ref-spacing-xsmall);max-width:var(--guit-sem-dimension-height-xlarge);min-height:0}.navigation__listItem{align-items:center;display:flex;flex-direction:column;width:100%}.navigation__addButton{align-items:center;display:flex;flex:0 0 auto;flex-direction:column;height:var(--guit-sem-dimension-height-large);margin-top:auto;width:var(--guit-sem-dimension-width-large)}.navigation__listItemText{color:var(--guit-sem-color-foreground-neutral-1);max-width:100%;-webkit-user-select:none;user-select:none}.navigation__iconButton{border-radius:var(--guit-ref-radius-3xsmall);height:var(--guit-sem-dimension-height-large);padding:var(--guit-ref-spacing-xsmall);width:var(--guit-sem-dimension-width-large)}.navigation__iconButton_selected{background-color:var(--guit-sem-color-background-selected-2);color:var(--guit-sem-color-foreground-inverse)}.navigation__iconButton_currentSelected{background-color:var(--guit-sem-color-background-neutral-1-pressed)}.navigation__iconButton_disabled{background-color:var(--guit-sem-color-background-neutral-1);pointer-events:none}.navigation__iconButton_disabled,.navigation__iconButton_disabled+.navigation__listItemText{color:var(--guit-sem-color-foreground-disabled)}.navigation__iconButton_pointer_none{pointer-events:none}.navigation__iconButton:not(.navigation__iconButton_selected,.navigation__iconButton_disabled){color:var(--guit-sem-color-foreground-neutral-2)}.navigation__iconButton:not(.navigation__iconButton_selected,.navigation__iconButton_disabled):hover{background-color:var(--guit-sem-color-background-neutral-1-hover)}.navigation__iconButton:not(.navigation__iconButton_selected,.navigation__iconButton_disabled):active{background-color:var(--guit-sem-color-background-neutral-1-pressed)}.navigation__divider{flex:0 0 auto}.navigation__menu{border-inline-end:var(--guit-ref-border-width-thin) var(--guit-ref-border-style-solid) var(--guit-sem-color-border-neutral-2);display:flex;height:100%;width:20rem}.navigation__menu_wrapper{height:100%;padding:var(--guit-ref-spacing-3xsmall) var(--guit-ref-spacing-xsmall)}.navigationItem,.navigation__menu_wrapper{display:flex;flex-direction:column;gap:var(--guit-ref-spacing-3xsmall);width:100%}.navigationItem__button{border-radius:var(--guit-ref-radius-3xsmall);display:flex;gap:var(--guit-ref-spacing-xsmall);padding:var(--guit-ref-spacing-xsmall) var(--guit-ref-spacing-xsmall) var(--guit-ref-spacing-xsmall) var(--guit-ref-spacing-medium);width:100%}.navigationItem__button_render{color:inherit}.navigationItem__button:hover{background-color:var(--guit-sem-color-background-neutral-1-hover)}.navigationItem__button:active{background-color:var(--guit-sem-color-background-neutral-1-pressed)}.navigationItem__button_selected{color:var(--guit-sem-color-foreground-selected)}.navigationItem__button_selected_noChildren{background:var(--guit-sem-color-background-neutral-3);color:var(--guit-sem-color-foreground-accent-blue)}.navigationItem__button_pointer_none{pointer-events:none}.navigationItem__button_disabled{background-color:var(--guit-sem-color-background-neutral-1);color:var(--guit-sem-color-foreground-disabled);pointer-events:none}.navigationItem__button_shift_1{padding-inline-start:var(--guit-ref-spacing-5xlarge)}.navigationItem__button_shift_2{padding-inline-start:var(--guit-ref-spacing-8xlarge)}.navigationItem__button_shift_3{padding-inline-start:var(--guit-ref-spacing-9xlarge)}.navigationItem__button_shift_4{padding-inline-start:var(--guit-ref-spacing-10xlarge)}.navigationItem__chevron{margin-left:auto}.navigationItem__chevron_open{transform:rotate(90deg)}";
|
|
136
172
|
styleInject(css_248z);
|
|
137
173
|
|
|
174
|
+
const ELEMENT_HEIGHT = 62;
|
|
138
175
|
const findPath = (navigationData, targetPath, currentPath = []) => {
|
|
139
176
|
for (let i = 0; i < navigationData.length; i++) {
|
|
140
177
|
const item = navigationData[i];
|
|
@@ -154,26 +191,25 @@ const hasDataAndChildren = (data, index) => {
|
|
|
154
191
|
var _a, _b;
|
|
155
192
|
return !!(data && index !== null && ((_a = data[index]) === null || _a === void 0 ? void 0 : _a.children) && ((_b = data[index].children) === null || _b === void 0 ? void 0 : _b.length) > 0);
|
|
156
193
|
};
|
|
157
|
-
const NavMenuContent = ({ data, depth = 0, onClick, activePathIndex }) => {
|
|
194
|
+
const NavMenuContent = ({ data, depth = 0, onClick, activePathIndex, render }) => {
|
|
158
195
|
var _a;
|
|
159
196
|
if (!data)
|
|
160
197
|
return null;
|
|
161
198
|
return (_a = data.children) === null || _a === void 0 ? void 0 : _a.map((item, index) => {
|
|
162
199
|
const itemKey = `${item.title}-${item.path}`;
|
|
163
200
|
return (React__default.createElement(Fragment, { key: itemKey },
|
|
164
|
-
React__default.createElement(NavigationItem, { title: item.title, path: item.path, depth: depth, Icon: item.Icon, onClick: onClick, disabled: item.disabled, selected: index === (activePathIndex === null || activePathIndex === void 0 ? void 0 : activePathIndex[0]) }, item.children && (React__default.createElement(NavMenuContent, { data: item, depth: depth + 1, onClick: onClick, activePathIndex: activePathIndex === null || activePathIndex === void 0 ? void 0 : activePathIndex.slice(1) })))));
|
|
201
|
+
React__default.createElement(NavigationItem, { title: item.title, path: item.path, depth: depth, Icon: item.Icon, onClick: onClick, disabled: item.disabled, selected: index === (activePathIndex === null || activePathIndex === void 0 ? void 0 : activePathIndex[0]), render: render }, item.children && (React__default.createElement(NavMenuContent, { data: item, depth: depth + 1, onClick: onClick, activePathIndex: activePathIndex === null || activePathIndex === void 0 ? void 0 : activePathIndex.slice(1), render: render })))));
|
|
165
202
|
});
|
|
166
203
|
};
|
|
167
204
|
/**
|
|
168
205
|
* Navigation is a vertical component that appears on the left side of a user interface. It provides users with quick access to key features.
|
|
169
206
|
*/
|
|
170
|
-
const Navigation = ({ className, open, navigationData = [], activePath, onClick, navigationCreateData, onNavigationCreateDataClick, moreMenuTitle = "More" }) => {
|
|
207
|
+
const Navigation = ({ className, open, navigationData = [], activePath, onClick, navigationCreateData, onNavigationCreateDataClick, moreMenuTitle = "More", render }) => {
|
|
171
208
|
const [currentDataIndex, setCurrentDataIndex] = useState(null);
|
|
172
209
|
const [hoverDataIndex, setHoverDataIndex] = useState(null);
|
|
173
210
|
const [forceOpen, setForceOpen] = useState(false);
|
|
174
211
|
const [maxVisibleItems, setMaxVisibleItems] = useState(0);
|
|
175
212
|
const [activePathIndex, setActivePathIndex] = useState(null);
|
|
176
|
-
const [moreMenuDataActiveIndex, setMoreMenuDataActiveIndex] = useState(-1);
|
|
177
213
|
const [clonedNavigationData, setClonedNavigationData] = useState([]);
|
|
178
214
|
const navColRef = useRef(null);
|
|
179
215
|
const [propsForPopover, setPropsForPopover] = useState({});
|
|
@@ -213,11 +249,11 @@ const Navigation = ({ className, open, navigationData = [], activePath, onClick,
|
|
|
213
249
|
setMenuData(menuSliceData);
|
|
214
250
|
}, [maxVisibleItems, clonedNavigationData]);
|
|
215
251
|
useEffect(() => {
|
|
216
|
-
|
|
217
|
-
|
|
252
|
+
const navColRefCurrent = navColRef.current;
|
|
253
|
+
if (navColRefCurrent) {
|
|
254
|
+
const { scrollWidth, offsetWidth } = navColRefCurrent;
|
|
218
255
|
if (scrollWidth > offsetWidth) {
|
|
219
|
-
const containerHeight =
|
|
220
|
-
const ELEMENT_HEIGHT = 62;
|
|
256
|
+
const containerHeight = navColRefCurrent.offsetHeight;
|
|
221
257
|
const maxVisibleItemsWithGap = Math.floor(containerHeight / ELEMENT_HEIGHT);
|
|
222
258
|
setMaxVisibleItems(maxVisibleItemsWithGap);
|
|
223
259
|
}
|
|
@@ -225,7 +261,7 @@ const Navigation = ({ className, open, navigationData = [], activePath, onClick,
|
|
|
225
261
|
setMaxVisibleItems(clonedNavigationData.length);
|
|
226
262
|
}
|
|
227
263
|
}
|
|
228
|
-
}, [navColRef
|
|
264
|
+
}, [navColRef, clonedNavigationData, height]);
|
|
229
265
|
useEffect(() => {
|
|
230
266
|
const lastVisibleItemIndex = maxVisibleItems - 1;
|
|
231
267
|
if (lastVisibleItemIndex === -1)
|
|
@@ -277,54 +313,49 @@ const Navigation = ({ className, open, navigationData = [], activePath, onClick,
|
|
|
277
313
|
}
|
|
278
314
|
}
|
|
279
315
|
};
|
|
280
|
-
const onMoreMenuItemsClickHandler = (
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
316
|
+
const onMoreMenuItemsClickHandler = (menuItemProps) => {
|
|
317
|
+
const indexInMenuData = Number(menuItemProps.id);
|
|
318
|
+
const originalIndex = maxVisibleItems + indexInMenuData;
|
|
319
|
+
const clickedItem = clonedNavigationData[originalIndex];
|
|
320
|
+
if (!clickedItem)
|
|
321
|
+
return;
|
|
322
|
+
setCurrentDataIndex(originalIndex);
|
|
323
|
+
setForceOpen(hasDataAndChildren(clonedNavigationData, originalIndex));
|
|
287
324
|
setHoverDataIndex(null);
|
|
288
|
-
if (
|
|
289
|
-
onClick(
|
|
325
|
+
if (clickedItem.path && onClick) {
|
|
326
|
+
onClick(clickedItem.path);
|
|
290
327
|
}
|
|
291
|
-
setActivePathIndex([maxVisibleItems - 1]);
|
|
292
328
|
};
|
|
293
329
|
const onNavigationCreateDataClickHandler = (item) => onNavigationCreateDataClick === null || onNavigationCreateDataClick === void 0 ? void 0 : onNavigationCreateDataClick(item);
|
|
294
|
-
useEffect(() => {
|
|
295
|
-
if (!(clonedNavigationData.length > maxVisibleItems))
|
|
296
|
-
return;
|
|
297
|
-
const index = activePathIndex === null || activePathIndex === void 0 ? void 0 : activePathIndex[0];
|
|
298
|
-
if (typeof index === "number" && index >= maxVisibleItems) {
|
|
299
|
-
setMoreMenuDataActiveIndex(maxVisibleItems - index);
|
|
300
|
-
}
|
|
301
|
-
else {
|
|
302
|
-
setMoreMenuDataActiveIndex(-1);
|
|
303
|
-
}
|
|
304
|
-
}, [maxVisibleItems, activePathIndex]);
|
|
305
330
|
const onCreateMenuClickHandler = (isOpen) => {
|
|
306
331
|
setIsCreateMenuOpen(isOpen);
|
|
307
332
|
};
|
|
308
|
-
return (React__default.createElement("div", { className: classNames("navigation", className), role: "navigation" }, isMobileBreakpoint ? (
|
|
309
|
-
// todo create navigation mobile
|
|
310
|
-
React__default.createElement("div", null, "Mobile Navigation")) : (React__default.createElement(React__default.Fragment, null,
|
|
333
|
+
return (React__default.createElement("div", { className: classNames("navigation", className), role: "navigation" }, isMobileBreakpoint ? (React__default.createElement("div", null, "Mobile Navigation")) : (React__default.createElement(React__default.Fragment, null,
|
|
311
334
|
React__default.createElement("nav", { className: "navigation__list" },
|
|
312
335
|
React__default.createElement("div", { className: "navigation__listWrapper" },
|
|
313
|
-
React__default.createElement("div", { className: "navigation__listItems", ref: navColRef }, clonedNavigationData === null || clonedNavigationData === void 0 ? void 0 : clonedNavigationData.map((item, index) => {
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
React__default.createElement(
|
|
318
|
-
React__default.createElement(
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
? activePathIndex.slice(1)
|
|
322
|
-
: null })))))));
|
|
323
|
-
})),
|
|
336
|
+
React__default.createElement("div", { className: "navigation__listItems", ref: navColRef }, clonedNavigationData === null || clonedNavigationData === void 0 ? void 0 : clonedNavigationData.map((item, index) => (React__default.createElement(Fragment, { key: `${item.title}-${item.path}` },
|
|
337
|
+
React__default.createElement(NavigationColItem, { isVisible: index < maxVisibleItems, Icon: item.Icon, title: item.title, onClick: onNavigationColItemClick, index: index, path: item.path, opened: forceOpen, currentSelected: currentDataIndex === index, selected: index === (activePathIndex === null || activePathIndex === void 0 ? void 0 : activePathIndex[0]), onMouseEnter: onMouseEnterHandler, disabled: item.disabled, propsForPopover: hoverDataIndex === index ? propsForPopover : {}, hasChildren: item.children && item.children.length > 0, render: render }),
|
|
338
|
+
hoverDataIndex !== null && item.children && item.children.length > 0 && (React__default.createElement(Popover, { setProps: setPropsForPopover, size: "small", position: "right-top", withArrow: true, trigger: "hover", margin: 20, disableReposition: false, ref: popoverRef },
|
|
339
|
+
React__default.createElement(PopoverBody, { withPadding: false },
|
|
340
|
+
React__default.createElement("div", { className: "navigation__menu_wrapper" },
|
|
341
|
+
React__default.createElement(NavMenuContent, { data: clonedNavigationData[hoverDataIndex], onClick: onItemClickHandler, activePathIndex: activePathIndex && hoverDataIndex === activePathIndex[0]
|
|
342
|
+
? activePathIndex.slice(1)
|
|
343
|
+
: null, render: render }))))))))),
|
|
324
344
|
clonedNavigationData.length > maxVisibleItems && (React__default.createElement(React__default.Fragment, null,
|
|
325
345
|
React__default.createElement(NavigationColItem, { Icon: SvgThreeDotsHorizontal, title: moreMenuTitle, isVisible: true, propsForPopover: menuPropsForPopover }),
|
|
326
|
-
React__default.createElement(Menu, { position: "right-bottom", onChange: onMoreMenuItemsClickHandler, setPropsForPopover: setMenuPropsForPopover }, menuData.map((
|
|
327
|
-
|
|
346
|
+
React__default.createElement(Menu, { position: "right-bottom", onChange: onMoreMenuItemsClickHandler, setPropsForPopover: setMenuPropsForPopover }, menuData.map((item, index) => {
|
|
347
|
+
const isParentItem = !!item.children && item.children.length > 0;
|
|
348
|
+
const menuItemRender = render && item.path && !isParentItem
|
|
349
|
+
? (menuLinkData) => render({
|
|
350
|
+
path: item.path,
|
|
351
|
+
title: menuLinkData.title,
|
|
352
|
+
isActive: activePath === item.path,
|
|
353
|
+
hasChildren: isParentItem,
|
|
354
|
+
isDisabled: item.disabled,
|
|
355
|
+
Icon: item.Icon
|
|
356
|
+
})
|
|
357
|
+
: undefined;
|
|
358
|
+
return (React__default.createElement(MenuItem, { key: `menuitem-${item.title}-${item.path || index}`, id: index, IconBefore: item.Icon, selected: activePath === item.path, disabled: item.disabled, render: menuItemRender }, item.title));
|
|
328
359
|
})))),
|
|
329
360
|
navigationCreateData && (React__default.createElement(React__default.Fragment, null,
|
|
330
361
|
React__default.createElement(Button, Object.assign({ onClick: () => { }, Icon: isCreateMenuOpen ? SvgX : SvgPlus, size: "large", appearance: "secondary", className: "navigation__addButton" }, propsForCreatePopover)),
|
|
@@ -339,7 +370,7 @@ const Navigation = ({ className, open, navigationData = [], activePath, onClick,
|
|
|
339
370
|
React__default.createElement("div", { className: "navigation__menu_wrapper" },
|
|
340
371
|
React__default.createElement(NavMenuContent, { data: clonedNavigationData[currentDataIndex], onClick: onItemClickHandler, activePathIndex: activePathIndex && currentDataIndex === activePathIndex[0]
|
|
341
372
|
? activePathIndex.slice(1)
|
|
342
|
-
: null })))))))));
|
|
373
|
+
: null, render: render })))))))));
|
|
343
374
|
};
|
|
344
375
|
|
|
345
376
|
export { Navigation as default };
|
|
@@ -28,7 +28,7 @@ interface IMenuProps {
|
|
|
28
28
|
*/
|
|
29
29
|
children: ReactElement | ReactElement[];
|
|
30
30
|
/**
|
|
31
|
-
*
|
|
31
|
+
* Indicates whether the menu is in a loading state. If true, a loading indicator is displayed instead of the menu items.
|
|
32
32
|
*/
|
|
33
33
|
loading?: boolean;
|
|
34
34
|
/**
|
|
@@ -38,9 +38,9 @@ interface IMenuProps {
|
|
|
38
38
|
/**
|
|
39
39
|
* Callback function hat returns all provided menu item props when a menu item is selected.
|
|
40
40
|
*/
|
|
41
|
-
onChange
|
|
41
|
+
onChange?: (item: IMenuItemProps) => void;
|
|
42
42
|
/**
|
|
43
|
-
*
|
|
43
|
+
* If true, enables swapping behavior, modifying the appearance and behavior of the menu.
|
|
44
44
|
*/
|
|
45
45
|
swappable?: boolean;
|
|
46
46
|
/**
|
|
@@ -54,8 +54,8 @@ interface IMenuProps {
|
|
|
54
54
|
*/
|
|
55
55
|
size?: SizeType;
|
|
56
56
|
/**
|
|
57
|
-
* Position of the Menu first popover, relative to the reference (trigger, anchor) element.<br
|
|
58
|
-
* Possible values: `bottom-center | bottom-left | bottom-right | left-bottom | left-center` <br
|
|
57
|
+
* Position of the Menu first popover, relative to the reference (trigger, anchor) element.<br/>
|
|
58
|
+
* Possible values: `bottom-center | bottom-left | bottom-right | left-bottom | left-center` <br/> `left-top | right-bottom | right-center | right-top | top-center | top-left | top-right | auto`
|
|
59
59
|
*/
|
|
60
60
|
position?: IPopoverProps["position"];
|
|
61
61
|
/**
|
|
@@ -54,7 +54,7 @@ interface IMenuItemProps {
|
|
|
54
54
|
*/
|
|
55
55
|
paths?: string[];
|
|
56
56
|
/**
|
|
57
|
-
*
|
|
57
|
+
* Indicates whether the menu is in a loading state. If true, a loading indicator is displayed instead of the menu items.
|
|
58
58
|
*/
|
|
59
59
|
loading?: boolean;
|
|
60
60
|
/**
|
|
@@ -62,6 +62,13 @@ interface IMenuItemProps {
|
|
|
62
62
|
*/
|
|
63
63
|
loadingText?: string;
|
|
64
64
|
generatedId?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Custom render function for the menu item.
|
|
67
|
+
*/
|
|
68
|
+
render?: (linkData: {
|
|
69
|
+
id: number | string;
|
|
70
|
+
title?: string;
|
|
71
|
+
}) => ReactNode;
|
|
65
72
|
}
|
|
66
73
|
declare const MenuItem: FC<IMenuItemProps>;
|
|
67
74
|
export { IMenuItemProps, MenuItem as default };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FC } from "react";
|
|
1
|
+
import { FC, ReactNode } from "react";
|
|
2
2
|
import { IMenuItemProps } from "@components/molecules/Menu";
|
|
3
3
|
import "./Navigation.scss";
|
|
4
4
|
export interface INavigationData {
|
|
@@ -43,6 +43,17 @@ interface INavigationProps {
|
|
|
43
43
|
* Optional custom title for the "More" menu.
|
|
44
44
|
*/
|
|
45
45
|
moreMenuTitle?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Custom render function for navigation links.
|
|
48
|
+
*/
|
|
49
|
+
render?: (linkData: {
|
|
50
|
+
path?: string;
|
|
51
|
+
title?: string;
|
|
52
|
+
isActive?: boolean;
|
|
53
|
+
hasChildren?: boolean;
|
|
54
|
+
isDisabled?: boolean;
|
|
55
|
+
Icon?: FC;
|
|
56
|
+
}) => ReactNode;
|
|
46
57
|
}
|
|
47
58
|
export declare const findPath: (navigationData: INavigationData[], targetPath: string, currentPath?: number[]) => number[] | null;
|
|
48
59
|
/**
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { FC, ReactNode } from "react";
|
|
2
2
|
import { IconProps } from "@geneui/icons";
|
|
3
|
+
import { INavigationProps } from "../Navigation";
|
|
3
4
|
interface INavigationItemProps {
|
|
4
5
|
title: string;
|
|
5
|
-
children?:
|
|
6
|
+
children?: ReactNode;
|
|
6
7
|
onClick?: (path: string) => void;
|
|
7
8
|
disabled?: boolean;
|
|
8
9
|
selected?: boolean;
|
|
9
10
|
depth: number;
|
|
10
11
|
Icon?: FC<IconProps>;
|
|
11
12
|
path?: string;
|
|
13
|
+
render?: INavigationProps["render"];
|
|
12
14
|
}
|
|
13
15
|
declare const NavigationItem: FC<INavigationItemProps>;
|
|
14
16
|
export { INavigationItemProps, NavigationItem as default };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FC } from "react";
|
|
2
2
|
import { IconProps } from "@geneui/icons";
|
|
3
|
+
import { INavigationProps } from "../Navigation";
|
|
3
4
|
interface INavigationColItemProps {
|
|
4
5
|
Icon?: FC<IconProps>;
|
|
5
6
|
selected?: boolean;
|
|
@@ -14,6 +15,7 @@ interface INavigationColItemProps {
|
|
|
14
15
|
isVisible?: boolean;
|
|
15
16
|
hasChildren?: boolean;
|
|
16
17
|
currentSelected?: boolean;
|
|
18
|
+
render?: INavigationProps["render"];
|
|
17
19
|
}
|
|
18
20
|
declare const NavigationColItem: FC<INavigationColItemProps>;
|
|
19
21
|
export { INavigationColItemProps, NavigationColItem as default };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geneui/components",
|
|
3
3
|
"description": "The Gene UI components library designed for BI tools",
|
|
4
|
-
"version": "3.0.0-next-
|
|
4
|
+
"version": "3.0.0-next-67f77e7-11082025",
|
|
5
5
|
"author": "SoftConstruct",
|
|
6
6
|
"homepage": "https://github.com/softconstruct/gene-ui-components#readme",
|
|
7
7
|
"repository": {
|