@uxf/ui 11.111.2 → 11.112.1

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/css/menu.css CHANGED
@@ -4,11 +4,25 @@
4
4
  --uxf-menu-item-gap: 12px;
5
5
  --uxf-menu-item-px: 12px;
6
6
  --uxf-menu-item-border-radius: 8px;
7
+ --uxf-menu-item-icon-width: 20px;
8
+ --uxf-menu-badge-indicator-color: var(--uxf-color-negative-surface-default);
9
+ --uxf-menu-badge-indicator-size: 8px;
7
10
  }
8
11
 
9
12
  .uxf-menu {
10
13
  font-size: theme("fontSize.sm");
11
14
  padding: 4px;
15
+
16
+ &.is-collapsed {
17
+ .uxf-menu-item__badge-indicator {
18
+ display: block;
19
+ }
20
+
21
+ .uxf-menu-item__label,
22
+ .uxf-menu-item__right-element {
23
+ display: none;
24
+ }
25
+ }
12
26
  }
13
27
 
14
28
  .uxf-menu-item {
@@ -16,7 +30,6 @@
16
30
  background-color: var(--uxf-menu-item-background-color);
17
31
  border-radius: var(--uxf-menu-item-border-radius);
18
32
  color: black;
19
- cursor: pointer;
20
33
  display: flex;
21
34
  flex-direction: row;
22
35
  gap: var(--uxf-menu-item-gap);
@@ -25,12 +38,15 @@
25
38
  padding: 4px var(--uxf-menu-item-px);
26
39
  width: 100%;
27
40
 
28
- &:hover {
41
+ &.is-hoverable:hover {
29
42
  --uxf-menu-item-background-color: var(--uxf-color-base-surface-main-hover);
43
+
44
+ cursor: pointer;
30
45
  }
31
46
 
32
47
  &.is-active:not(.uxf-menu-item--level-1),
33
- &.is-active.has-no-children {
48
+ &.is-active.has-no-children,
49
+ .uxf-menu.is-collapsed &.is-active.uxf-menu-item--level-1 {
34
50
  --uxf-menu-item-background-color: #e5e7eb;
35
51
 
36
52
  font-weight: 500;
@@ -50,6 +66,25 @@
50
66
  }
51
67
  }
52
68
 
69
+ .uxf-menu-item__badge-indicator {
70
+ background-color: var(--uxf-menu-badge-indicator-color);
71
+ border-radius: 999px;
72
+ display: none;
73
+ height: var(--uxf-menu-badge-indicator-size);
74
+ position: absolute;
75
+ right: 0;
76
+ top: -4px;
77
+ width: var(--uxf-menu-badge-indicator-size);
78
+ }
79
+
80
+ .uxf-menu-item__icon-wrapper {
81
+ align-items: center;
82
+ display: flex;
83
+ justify-content: center;
84
+ position: relative;
85
+ width: var(--uxf-menu-item-icon-width);
86
+ }
87
+
53
88
  .uxf-menu-item__icon {
54
89
  height: var(--uxf-menu-icon-size);
55
90
  width: var(--uxf-menu-icon-size);
@@ -73,7 +108,8 @@
73
108
  }
74
109
  }
75
110
 
76
- .uxf-menu__submenu {
111
+ .uxf-menu__submenu:not(.uxf-menu__submenu--in-popover),
112
+ .uxf-menu__submenu.is-parent-collapsed {
77
113
  padding-left: calc(var(--uxf-menu-item-gap) + var(--uxf-menu-icon-size));
78
114
  position: relative;
79
115
 
@@ -90,7 +126,7 @@
90
126
  .uxf-menu-item {
91
127
  position: relative;
92
128
 
93
- &:hover {
129
+ &.is-hoverable:hover {
94
130
  &::before {
95
131
  background-color: #0f1012;
96
132
  bottom: 0;
@@ -1,4 +1,4 @@
1
- import { ReactElement } from "react";
1
+ import React, { ReactElement } from "react";
2
2
  import { IconName } from "../../icon/types";
3
3
  import { NextLink } from "../../utils/next-link";
4
4
  interface MenuItemButtonProps {
@@ -13,5 +13,5 @@ interface MenuItemButtonProps {
13
13
  isActive?: boolean;
14
14
  badge?: ReactElement;
15
15
  }
16
- export declare function MenuItemButton(props: MenuItemButtonProps): ReactElement;
16
+ export declare const MenuItemButton: React.ForwardRefExoticComponent<MenuItemButtonProps & React.RefAttributes<HTMLElement>>;
17
17
  export {};
@@ -1,27 +1,64 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
5
35
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.MenuItemButton = MenuItemButton;
36
+ exports.MenuItemButton = void 0;
37
+ const use_clickable_props_1 = require("@uxf/core-react/clickable/use-clickable-props");
7
38
  const cx_1 = require("@uxf/core/utils/cx");
8
39
  const is_nil_1 = require("@uxf/core/utils/is-nil");
9
40
  const is_not_nil_1 = require("@uxf/core/utils/is-not-nil");
10
41
  const icon_1 = require("@uxf/ui/icon");
11
- const react_1 = __importDefault(require("react"));
12
- function MenuItemButton(props) {
42
+ const react_1 = __importStar(require("react"));
43
+ exports.MenuItemButton = (0, react_1.forwardRef)((props, ref) => {
13
44
  var _a;
14
45
  const LinkComponent = (_a = props.LinkComponent) !== null && _a !== void 0 ? _a : "a";
15
46
  const className = (0, cx_1.cx)(`uxf-menu-item uxf-menu-item--level-${props.level}`, props.isOpen ? "is-open" : "is-close", props.isActive && "is-active", props.hasChildren ? "has-children" : "has-no-children", (0, is_nil_1.isNil)(props.icon) && "uxf-menu-item--no-icon");
47
+ const clickableProps = (0, use_clickable_props_1.useClickableProps)({ onClick: props.onClick, href: props.href, className });
16
48
  const content = (react_1.default.createElement(react_1.default.Fragment, null,
17
49
  (0, is_not_nil_1.isNotNil)(props.icon) && (react_1.default.createElement("div", { className: "uxf-menu-item__icon-wrapper" },
18
- react_1.default.createElement(icon_1.Icon, { className: "uxf-menu-item__icon", name: props.icon }))),
50
+ react_1.default.createElement(icon_1.Icon, { className: "uxf-menu-item__icon", name: props.icon }),
51
+ (0, is_not_nil_1.isNotNil)(props.badge) && react_1.default.createElement("div", { className: "uxf-menu-item__badge-indicator" }))),
19
52
  react_1.default.createElement("div", { className: "uxf-menu-item__label" }, props.label),
20
53
  react_1.default.createElement("div", { className: "uxf-menu-item__right-element" },
21
54
  (0, is_not_nil_1.isNotNil)(props.badge) && props.badge,
22
55
  props.hasChildren && (react_1.default.createElement(icon_1.Icon, { className: (0, cx_1.cx)("uxf-menu-item__open-icon", props.isOpen ? "is-open" : "is-close", props.isActive && "is-active"), name: "caretDown" })))));
23
56
  if ((0, is_not_nil_1.isNotNil)(props.href)) {
24
- return (react_1.default.createElement(LinkComponent, { className: className, href: props.href, onClick: props.onClick, title: props.label }, content));
57
+ return (react_1.default.createElement(LinkComponent, { ...clickableProps, href: props.href, ref: ref, title: props.label }, content));
58
+ }
59
+ if ((0, is_not_nil_1.isNotNil)(props.onClick)) {
60
+ return (react_1.default.createElement("button", { ...clickableProps, ref: ref, title: props.label }, content));
25
61
  }
26
- return (react_1.default.createElement("button", { className: className, onClick: props.onClick, title: props.label }, content));
27
- }
62
+ return (react_1.default.createElement("div", { className: className, ref: ref, title: props.label }, content));
63
+ });
64
+ exports.MenuItemButton.displayName = "UxfUiMenuItemButton";
@@ -2,11 +2,12 @@ import React from "react";
2
2
  import { NextLink } from "../../utils/next-link";
3
3
  import { ActiveTreeNode, MenuItemConfiguration } from "../types";
4
4
  interface Props {
5
- item: MenuItemConfiguration;
6
- activeTree: ActiveTreeNode;
7
5
  LinkComponent?: NextLink | "a";
8
- level: number;
6
+ activeTree: ActiveTreeNode;
7
+ isCollapsed?: boolean;
9
8
  isPopoverEnabled?: boolean;
9
+ item: MenuItemConfiguration;
10
+ level: number;
10
11
  }
11
12
  export declare function MenuItem(props: Props): React.JSX.Element;
12
13
  export {};
@@ -44,31 +44,39 @@ const popover_1 = require("../../popover/popover");
44
44
  const menu_item_button_1 = require("./menu-item-button");
45
45
  function MenuItem(props) {
46
46
  var _a, _b;
47
- const [isOpen, setIsOpen] = (0, react_1.useState)(props.activeTree.isActive);
47
+ const [isOpen, setIsOpen] = (0, react_1.useState)(props.activeTree.isActive && !props.isCollapsed);
48
48
  const button = (react_1.default.createElement(menu_item_button_1.MenuItemButton, { LinkComponent: (_b = (_a = props.item.as) !== null && _a !== void 0 ? _a : props.LinkComponent) !== null && _b !== void 0 ? _b : "a", badge: props.item.badge, hasChildren: (0, is_not_nil_1.isNotNil)(props.item.children) && (0, is_not_empty_1.isNotEmpty)(props.item.children), href: props.item.href, icon: props.item.icon, isActive: props.activeTree.isActive, isOpen: isOpen, label: props.item.label, level: props.level, onClick: () => {
49
49
  if ((0, is_not_nil_1.isNotNil)(props.item.onClick)) {
50
50
  props.item.onClick();
51
51
  }
52
52
  else {
53
- setIsOpen((prev) => !prev);
53
+ if (!props.isCollapsed) {
54
+ setIsOpen((prev) => !prev);
55
+ }
54
56
  }
55
57
  } }));
56
58
  if ((0, is_nil_1.isNil)(props.item.children) || (0, is_empty_1.isEmpty)(props.item.children)) {
59
+ if (props.isCollapsed) {
60
+ return (react_1.default.createElement(popover_1.Popover, { placement: "right-start", trigger: "hover" },
61
+ react_1.default.createElement(popover_1.Popover.Trigger, { asChild: true }, button),
62
+ !isOpen && (react_1.default.createElement(popover_1.Popover.Content, { className: "uxf-menu__popover" },
63
+ react_1.default.createElement(menu_item_button_1.MenuItemButton, { badge: props.item.badge, href: props.item.href, label: props.item.label, level: props.level, onClick: props.item.onClick })))));
64
+ }
57
65
  return button;
58
66
  }
59
67
  const children = props.item.children.map((item, index) => {
60
68
  var _a, _b;
61
- return (react_1.default.createElement(MenuItem, { LinkComponent: props.LinkComponent, activeTree: (_b = (_a = props.activeTree.children) === null || _a === void 0 ? void 0 : _a.at(index)) !== null && _b !== void 0 ? _b : (0, throw_error_1.throwError)("Active tree is not defined"), isPopoverEnabled: props.isPopoverEnabled, item: item, key: item.label, level: props.level + 1 }));
69
+ return (react_1.default.createElement(MenuItem, { LinkComponent: props.LinkComponent, activeTree: (_b = (_a = props.activeTree.children) === null || _a === void 0 ? void 0 : _a.at(index)) !== null && _b !== void 0 ? _b : (0, throw_error_1.throwError)("Active tree is not defined"), isPopoverEnabled: props.isPopoverEnabled, item: item, key: `${item.label}-${props.isCollapsed}-${props.isPopoverEnabled}`, level: props.level + 1 }));
62
70
  });
63
- if (!props.isPopoverEnabled) {
71
+ if (!props.isPopoverEnabled && !props.isCollapsed) {
64
72
  return (react_1.default.createElement("div", null,
65
73
  button,
66
74
  react_1.default.createElement("div", { className: "uxf-menu__submenu" }, isOpen && children)));
67
75
  }
68
76
  return (react_1.default.createElement(popover_1.Popover, { placement: "right-start", trigger: "hover" },
69
- react_1.default.createElement(popover_1.Popover.Trigger, null,
70
- react_1.default.createElement("div", null,
71
- button,
72
- isOpen && react_1.default.createElement("div", { className: "uxf-menu__submenu" }, children))),
73
- !isOpen && react_1.default.createElement(popover_1.Popover.Content, { className: "uxf-menu__popover" }, children)));
77
+ react_1.default.createElement(popover_1.Popover.Trigger, { asChild: true }, button),
78
+ isOpen && !props.isCollapsed && react_1.default.createElement("div", { className: "uxf-menu__submenu" }, children),
79
+ !isOpen && (react_1.default.createElement(popover_1.Popover.Content, { className: "uxf-menu__popover" },
80
+ props.isCollapsed && (react_1.default.createElement(menu_item_button_1.MenuItemButton, { badge: props.item.badge, label: props.item.label, level: props.level })),
81
+ react_1.default.createElement("div", { className: `uxf-menu__submenu uxf-menu__submenu--in-popover ${props.isCollapsed ? "is-parent-collapsed" : ""}` }, children)))));
74
82
  }
package/menu/menu.d.ts CHANGED
@@ -7,9 +7,10 @@ export type SimpleRouter = {
7
7
  pathParams?: RouterPathParams | null;
8
8
  };
9
9
  export interface MenuProps {
10
- configuration: MenuConfiguration;
11
- router: SimpleRouter;
12
10
  className?: string;
11
+ configuration: MenuConfiguration;
12
+ isCollapsed?: boolean;
13
13
  isPopoverEnabled?: boolean;
14
+ router: SimpleRouter;
14
15
  }
15
16
  export declare function Menu(props: MenuProps): React.JSX.Element;
package/menu/menu.js CHANGED
@@ -19,5 +19,5 @@ function createActiveTree(menuItem, router) {
19
19
  function Menu(props) {
20
20
  var _a;
21
21
  const activeTree = props.configuration.map((item) => createActiveTree(item, props.router));
22
- return (react_1.default.createElement("div", { className: `uxf-menu ${(_a = props.className) !== null && _a !== void 0 ? _a : ""}` }, props.configuration.map((item, index) => (react_1.default.createElement(menu_item_1.MenuItem, { activeTree: activeTree[index], isPopoverEnabled: props.isPopoverEnabled, item: item, key: item.label, level: 1 })))));
22
+ return (react_1.default.createElement("div", { className: `uxf-menu ${props.isCollapsed ? "is-collapsed" : ""} ${(_a = props.className) !== null && _a !== void 0 ? _a : ""}` }, props.configuration.map((item, index) => (react_1.default.createElement(menu_item_1.MenuItem, { activeTree: activeTree[index], isCollapsed: props.isCollapsed, isPopoverEnabled: props.isPopoverEnabled, item: item, key: `${item.label}-${props.isCollapsed}-${props.isPopoverEnabled}`, level: 1 })))));
23
23
  }
@@ -1,17 +1,49 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
5
35
  Object.defineProperty(exports, "__esModule", { value: true });
6
36
  exports.Default = Default;
7
- const react_1 = __importDefault(require("react"));
37
+ const react_1 = __importStar(require("react"));
8
38
  const badge_1 = require("../badge");
39
+ const toggle_1 = require("../toggle");
9
40
  const menu_1 = require("./menu");
10
41
  const CONFIGURATION = [
11
42
  {
12
- label: "UXF Web",
43
+ label: "UXF Web (active)",
13
44
  href: "https://www.uxf.cz",
14
45
  icon: "eye",
46
+ routeMatcher: () => true,
15
47
  },
16
48
  {
17
49
  label: "Link without children",
@@ -24,7 +56,7 @@ const CONFIGURATION = [
24
56
  icon: "file",
25
57
  badge: react_1.default.createElement(badge_1.Badge, null, "5"),
26
58
  children: [
27
- { label: "Link 1", icon: "bars" },
59
+ { label: "Link 1 (active)", icon: "bars", routeMatcher: () => true },
28
60
  { label: "Link 2", href: "/examples", icon: "copy" },
29
61
  { label: "Link with very very long text", href: "/examples", icon: "copy" },
30
62
  ],
@@ -41,6 +73,11 @@ const CONFIGURATION = [
41
73
  },
42
74
  ];
43
75
  function Default() {
44
- return (react_1.default.createElement("div", { className: "fixed inset-y-0 left-0 w-60 bg-white p-1" },
45
- react_1.default.createElement(menu_1.Menu, { configuration: CONFIGURATION, router: { pathname: "", pathParams: {} } })));
76
+ const [isCollapsed, setIsCollapsed] = (0, react_1.useState)(false);
77
+ const [isPopoverEnabled, setIsPopoverEnabled] = (0, react_1.useState)(false);
78
+ return (react_1.default.createElement("div", null,
79
+ react_1.default.createElement(toggle_1.Toggle, { label: "Collapsed", name: "collapsed", onChange: (value) => setIsCollapsed(value !== null && value !== void 0 ? value : false), value: isCollapsed }),
80
+ react_1.default.createElement(toggle_1.Toggle, { label: "Popover", name: "popover", onChange: (value) => setIsPopoverEnabled(value !== null && value !== void 0 ? value : false), value: isPopoverEnabled }),
81
+ react_1.default.createElement("div", { className: `fixed bottom-0 left-0 top-28 bg-white p-1 ${isCollapsed ? "w-15" : "w-60"}` },
82
+ react_1.default.createElement(menu_1.Menu, { configuration: CONFIGURATION, isCollapsed: isCollapsed, isPopoverEnabled: isPopoverEnabled, router: { pathname: "", pathParams: {} } }))));
46
83
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uxf/ui",
3
- "version": "11.111.2",
3
+ "version": "11.112.1",
4
4
  "description": "",
5
5
  "publishConfig": {
6
6
  "access": "public"