@selfcommunity/react-ui 0.11.0-alpha.95 → 0.11.0-alpha.97

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.
@@ -10,6 +10,7 @@ const classnames_1 = tslib_1.__importDefault(require("classnames"));
10
10
  const types_1 = require("@selfcommunity/types");
11
11
  const utils_1 = require("@selfcommunity/utils");
12
12
  const ComposerIconButton_1 = tslib_1.__importDefault(require("../ComposerIconButton"));
13
+ const seamless_scroll_polyfill_1 = require("seamless-scroll-polyfill");
13
14
  const PREFIX = 'SCBottomNavigation';
14
15
  const classes = {
15
16
  root: `${PREFIX}-root`,
@@ -84,11 +85,22 @@ function BottomNavigation(inProps) {
84
85
  const postOnlyStaffEnabled = preferences[react_core_1.SCPreferences.CONFIGURATIONS_POST_ONLY_STAFF_ENABLED].value;
85
86
  const contentAvailable = preferences[react_core_1.SCPreferences.CONFIGURATIONS_CONTENT_AVAILABILITY].value;
86
87
  const isIOS = (0, react_1.useMemo)(() => (0, utils_1.iOS)(), []);
88
+ const handleClickHome = (0, react_1.useCallback)(() => {
89
+ if (onClickHome) {
90
+ onClickHome();
91
+ }
92
+ else {
93
+ const pathName = window.location.pathname;
94
+ if (pathName && (pathName === '/' || pathName === scRoutingContext.url(react_core_1.SCRoutes.HOME_ROUTE_NAME, {}))) {
95
+ (0, seamless_scroll_polyfill_1.scroll)(window, { top: 0, behavior: 'smooth' });
96
+ }
97
+ }
98
+ }, [onClickHome]);
87
99
  // RENDER
88
100
  return ((0, jsx_runtime_1.jsx)(Root, Object.assign({ className: (0, classnames_1.default)(className, classes.root, { [classes.ios]: isIOS }) }, rest, { children: children
89
101
  ? children
90
102
  : [
91
- (0, jsx_runtime_1.jsx)(material_1.BottomNavigationAction, Object.assign({ className: classes.action, component: react_core_1.Link, to: scUserContext.user ? scRoutingContext.url(react_core_1.SCRoutes.HOME_ROUTE_NAME, {}) : '/', value: scUserContext.user ? scRoutingContext.url(react_core_1.SCRoutes.HOME_ROUTE_NAME, {}) : '/', icon: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "home" }) }, (onClickHome && { onClick: onClickHome })), "home"),
103
+ (0, jsx_runtime_1.jsx)(material_1.BottomNavigationAction, { className: classes.action, component: react_core_1.Link, to: scUserContext.user ? scRoutingContext.url(react_core_1.SCRoutes.HOME_ROUTE_NAME, {}) : '/', value: scUserContext.user ? scRoutingContext.url(react_core_1.SCRoutes.HOME_ROUTE_NAME, {}) : '/', icon: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "home" }), onClick: handleClickHome }, "home"),
92
104
  // (scUserContext.user || contentAvailable) && exploreStreamEnabled ? (
93
105
  // <BottomNavigationAction
94
106
  // key="explore"
@@ -3,5 +3,6 @@ import { CategoryProps } from '../Category';
3
3
  export interface DefaultDrawerContentProps extends BoxProps {
4
4
  CategoryItemProps?: CategoryProps;
5
5
  tagImage?: string;
6
+ onClickHome?: () => void;
6
7
  }
7
8
  export default function DefaultDrawerContent(inProps: DefaultDrawerContentProps): JSX.Element;
@@ -14,6 +14,7 @@ const system_1 = require("@mui/system");
14
14
  const BaseItem_1 = tslib_1.__importDefault(require("../../shared/BaseItem"));
15
15
  const formazione_1 = tslib_1.__importDefault(require("../../assets/custom/formazione"));
16
16
  const DefaultDrawerContent_1 = require("../../constants/DefaultDrawerContent");
17
+ const seamless_scroll_polyfill_1 = require("seamless-scroll-polyfill");
17
18
  const PREFIX = 'SCDefaultDrawerContent';
18
19
  const classes = {
19
20
  root: `${PREFIX}-root`,
@@ -31,7 +32,7 @@ function DefaultDrawerContent(inProps) {
31
32
  props: inProps,
32
33
  name: PREFIX
33
34
  });
34
- const { className, CategoryItemProps = { showTooltip: true }, tagImage = '/' } = props, rest = tslib_1.__rest(props, ["className", "CategoryItemProps", "tagImage"]);
35
+ const { className, CategoryItemProps = { showTooltip: true }, tagImage = '/', onClickHome } = props, rest = tslib_1.__rest(props, ["className", "CategoryItemProps", "tagImage", "onClickHome"]);
35
36
  // HOOKS
36
37
  const { categories } = (0, react_core_1.useSCFetchCategories)();
37
38
  const [categoriesOrdered, setCategoriesOrdered] = (0, react_1.useState)([]);
@@ -79,6 +80,17 @@ function DefaultDrawerContent(inProps) {
79
80
  const handleChange = (tagName) => (_event, isExpanded) => {
80
81
  setExpanded(isExpanded ? tagName : false);
81
82
  };
83
+ const handleClickHome = (0, react_1.useCallback)(() => {
84
+ if (onClickHome) {
85
+ onClickHome();
86
+ }
87
+ else {
88
+ const pathName = window.location.pathname;
89
+ if (pathName && (pathName === '/' || pathName === scRoutingContext.url(react_core_1.SCRoutes.HOME_ROUTE_NAME, {}))) {
90
+ (0, seamless_scroll_polyfill_1.scroll)(window, { top: 0, behavior: 'smooth' });
91
+ }
92
+ }
93
+ }, [onClickHome]);
82
94
  // Order categories
83
95
  (0, react_1.useEffect)(() => {
84
96
  if (!scUserContext.user || (scUserContext.user && showAllCategories)) {
@@ -111,7 +123,7 @@ function DefaultDrawerContent(inProps) {
111
123
  }
112
124
  });
113
125
  //order
114
- return ((0, jsx_runtime_1.jsxs)(Root, Object.assign({ className: (0, classnames_1.default)(className, classes.root) }, rest, { children: [(0, jsx_runtime_1.jsxs)(material_1.List, Object.assign({ className: classes.navigation }, { children: [scUserContext.user && ((0, jsx_runtime_1.jsx)(material_1.ListItem, Object.assign({ disablePadding: true }, { children: (0, jsx_runtime_1.jsxs)(material_1.ListItemButton, Object.assign({ component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.HOME_ROUTE_NAME, {}) }, { children: [(0, jsx_runtime_1.jsx)(material_1.ListItemIcon, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "home" }) }), (0, jsx_runtime_1.jsx)(material_1.ListItemText, { primary: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.home", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.home" }) })] })) }))), coursesEnabled && (scUserContext.user || contentAvailable) && ((0, jsx_runtime_1.jsx)(material_1.ListItem, Object.assign({ disablePadding: true }, { children: (0, jsx_runtime_1.jsxs)(material_1.ListItemButton, Object.assign({ component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.COURSES_ROUTE_NAME, {}) }, { children: [(0, jsx_runtime_1.jsx)(material_1.ListItemIcon, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "courses" }) }), (0, jsx_runtime_1.jsx)(material_1.ListItemText, { primary: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.courses", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.courses" }) })] })) }))), groupsEnabled && scUserContext.user && ((0, jsx_runtime_1.jsx)(material_1.ListItem, Object.assign({ disablePadding: true }, { children: (0, jsx_runtime_1.jsxs)(material_1.ListItemButton, Object.assign({ component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.GROUPS_ROUTE_NAME, {}) }, { children: [(0, jsx_runtime_1.jsx)(material_1.ListItemIcon, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "groups" }) }), (0, jsx_runtime_1.jsx)(material_1.ListItemText, { primary: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.groups", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.groups" }) })] })) }))), eventsEnabled && (scUserContext.user || contentAvailable) && ((0, jsx_runtime_1.jsx)(material_1.ListItem, Object.assign({ disablePadding: true }, { children: (0, jsx_runtime_1.jsxs)(material_1.ListItemButton, Object.assign({ component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.EVENTS_ROUTE_NAME, {}) }, { children: [(0, jsx_runtime_1.jsx)(material_1.ListItemIcon, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "CalendarIcon" }) }), (0, jsx_runtime_1.jsx)(material_1.ListItemText, { primary: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.events", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.events" }) })] })) }))), exploreStreamEnabled && (contentAvailable || scUserContext.user) && ((0, jsx_runtime_1.jsx)(material_1.ListItem, Object.assign({ disablePadding: true }, { children: (0, jsx_runtime_1.jsxs)(material_1.ListItemButton, Object.assign({ component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.EXPLORE_ROUTE_NAME, {}) }, { children: [(0, jsx_runtime_1.jsx)(material_1.ListItemIcon, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "explore" }) }), (0, jsx_runtime_1.jsx)(material_1.ListItemText, { primary: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.explore", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.explore" }) })] })) })))] })), (0, jsx_runtime_1.jsx)(material_1.Divider, {}), (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "subtitle1", className: classes.title }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.category.title", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.category.title" }) })), !categoriesOrdered.length && ((0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1", className: classes.noResults }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.category.noResults", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.category.noResults" }) }))), (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [Object.entries(taggedCategories).map(([tagName, categories]) => {
126
+ return ((0, jsx_runtime_1.jsxs)(Root, Object.assign({ className: (0, classnames_1.default)(className, classes.root) }, rest, { children: [(0, jsx_runtime_1.jsxs)(material_1.List, Object.assign({ className: classes.navigation }, { children: [scUserContext.user && ((0, jsx_runtime_1.jsx)(material_1.ListItem, Object.assign({ disablePadding: true }, { children: (0, jsx_runtime_1.jsxs)(material_1.ListItemButton, Object.assign({ component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.HOME_ROUTE_NAME, {}), onClickHome: handleClickHome }, { children: [(0, jsx_runtime_1.jsx)(material_1.ListItemIcon, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "home" }) }), (0, jsx_runtime_1.jsx)(material_1.ListItemText, { primary: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.home", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.home" }) })] })) }))), coursesEnabled && (scUserContext.user || contentAvailable) && ((0, jsx_runtime_1.jsx)(material_1.ListItem, Object.assign({ disablePadding: true }, { children: (0, jsx_runtime_1.jsxs)(material_1.ListItemButton, Object.assign({ component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.COURSES_ROUTE_NAME, {}) }, { children: [(0, jsx_runtime_1.jsx)(material_1.ListItemIcon, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "courses" }) }), (0, jsx_runtime_1.jsx)(material_1.ListItemText, { primary: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.courses", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.courses" }) })] })) }))), groupsEnabled && scUserContext.user && ((0, jsx_runtime_1.jsx)(material_1.ListItem, Object.assign({ disablePadding: true }, { children: (0, jsx_runtime_1.jsxs)(material_1.ListItemButton, Object.assign({ component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.GROUPS_ROUTE_NAME, {}) }, { children: [(0, jsx_runtime_1.jsx)(material_1.ListItemIcon, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "groups" }) }), (0, jsx_runtime_1.jsx)(material_1.ListItemText, { primary: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.groups", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.groups" }) })] })) }))), eventsEnabled && (scUserContext.user || contentAvailable) && ((0, jsx_runtime_1.jsx)(material_1.ListItem, Object.assign({ disablePadding: true }, { children: (0, jsx_runtime_1.jsxs)(material_1.ListItemButton, Object.assign({ component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.EVENTS_ROUTE_NAME, {}) }, { children: [(0, jsx_runtime_1.jsx)(material_1.ListItemIcon, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "CalendarIcon" }) }), (0, jsx_runtime_1.jsx)(material_1.ListItemText, { primary: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.events", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.events" }) })] })) }))), exploreStreamEnabled && (contentAvailable || scUserContext.user) && ((0, jsx_runtime_1.jsx)(material_1.ListItem, Object.assign({ disablePadding: true }, { children: (0, jsx_runtime_1.jsxs)(material_1.ListItemButton, Object.assign({ component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.EXPLORE_ROUTE_NAME, {}) }, { children: [(0, jsx_runtime_1.jsx)(material_1.ListItemIcon, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "explore" }) }), (0, jsx_runtime_1.jsx)(material_1.ListItemText, { primary: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.explore", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.explore" }) })] })) })))] })), (0, jsx_runtime_1.jsx)(material_1.Divider, {}), (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "subtitle1", className: classes.title }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.category.title", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.category.title" }) })), !categoriesOrdered.length && ((0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1", className: classes.noResults }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.category.noResults", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.category.noResults" }) }))), (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [Object.entries(taggedCategories).map(([tagName, categories]) => {
115
127
  var _a;
116
128
  if (!categories.length || !((_a = categories[0].tags) === null || _a === void 0 ? void 0 : _a.length))
117
129
  return null;
@@ -16,6 +16,7 @@ const types_1 = require("@selfcommunity/types");
16
16
  const react_core_1 = require("@selfcommunity/react-core");
17
17
  const NavigationMenuIconButton_1 = tslib_1.__importDefault(require("../NavigationMenuIconButton"));
18
18
  const constants_1 = require("./constants");
19
+ const seamless_scroll_polyfill_1 = require("seamless-scroll-polyfill");
19
20
  const classes = {
20
21
  root: `${constants_1.PREFIX}-root`,
21
22
  logo: `${constants_1.PREFIX}-logo`,
@@ -99,7 +100,7 @@ function NavigationToolbar(inProps) {
99
100
  props: inProps,
100
101
  name: constants_1.PREFIX
101
102
  });
102
- const { value = '', className = '', disableSearch = false, disableComposer = false, SearchAutocompleteComponentProps = {}, startActions = null, endActions = null, NavigationSettingsIconButtonComponent = NavigationSettingsIconButton_1.default, NavigationMenuIconButtonComponentProps = {}, NavigationMenuIconButtonComponent = NavigationMenuIconButton_1.default, children = null, NotificationMenuProps = {}, ComposerIconButtonProps = {}, onClickHome, onOpenNotificationMenu, onCloseNotificationMenu } = props, rest = tslib_1.__rest(props, ["value", "className", "disableSearch", "disableComposer", "SearchAutocompleteComponentProps", "startActions", "endActions", "NavigationSettingsIconButtonComponent", "NavigationMenuIconButtonComponentProps", "NavigationMenuIconButtonComponent", "children", "NotificationMenuProps", "ComposerIconButtonProps", "onClickHome", "onOpenNotificationMenu", "onCloseNotificationMenu"]);
103
+ const { value = '', className = '', disableSearch = false, disableComposer = false, SearchAutocompleteComponentProps = {}, startActions = null, endActions = null, NavigationSettingsIconButtonComponent = NavigationSettingsIconButton_1.default, NavigationMenuIconButtonComponent = NavigationMenuIconButton_1.default, NavigationMenuIconButtonComponentProps = {}, children = null, NotificationMenuProps = {}, ComposerIconButtonProps = {}, onClickHome, onOpenNotificationMenu, onCloseNotificationMenu } = props, rest = tslib_1.__rest(props, ["value", "className", "disableSearch", "disableComposer", "SearchAutocompleteComponentProps", "startActions", "endActions", "NavigationSettingsIconButtonComponent", "NavigationMenuIconButtonComponent", "NavigationMenuIconButtonComponentProps", "children", "NotificationMenuProps", "ComposerIconButtonProps", "onClickHome", "onOpenNotificationMenu", "onCloseNotificationMenu"]);
103
104
  // CONTEXT
104
105
  const scUserContext = (0, react_core_1.useSCUser)();
105
106
  const scRoutingContext = (0, react_core_1.useSCRouting)();
@@ -147,11 +148,22 @@ function NavigationToolbar(inProps) {
147
148
  setAnchorNotification(null);
148
149
  onCloseNotificationMenu && onCloseNotificationMenu();
149
150
  };
151
+ const handleClickHome = (0, react_1.useCallback)(() => {
152
+ if (onClickHome) {
153
+ onClickHome();
154
+ }
155
+ else {
156
+ const pathName = window.location.pathname;
157
+ if (pathName && (pathName === '/' || pathName === scRoutingContext.url(react_core_1.SCRoutes.HOME_ROUTE_NAME, {}))) {
158
+ (0, seamless_scroll_polyfill_1.scroll)(window, { top: 0, behavior: 'smooth' });
159
+ }
160
+ }
161
+ }, [onClickHome]);
150
162
  // RENDER
151
163
  if (scUserContext.loading) {
152
164
  return (0, jsx_runtime_1.jsx)(Skeleton_1.default, {});
153
165
  }
154
- const _children = children || ((0, jsx_runtime_1.jsxs)(material_1.Box, Object.assign({ className: classes.navigation }, { children: [scUserContext.user && ((0, jsx_runtime_1.jsx)(material_1.IconButton, Object.assign({ className: (0, classnames_1.default)(classes.home, { [classes.active]: value.startsWith(scRoutingContext.url(react_core_1.SCRoutes.HOME_ROUTE_NAME, {})) }), "aria-label": "Home", to: scRoutingContext.url(react_core_1.SCRoutes.HOME_ROUTE_NAME, {}), component: react_core_1.Link }, (onClickHome && { onClick: onClickHome }), { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "home" }) }))), preferences[react_core_1.SCPreferences.CONFIGURATIONS_EXPLORE_STREAM_ENABLED] &&
166
+ const _children = children || ((0, jsx_runtime_1.jsxs)(material_1.Box, Object.assign({ className: classes.navigation }, { children: [scUserContext.user && ((0, jsx_runtime_1.jsx)(material_1.IconButton, Object.assign({ className: (0, classnames_1.default)(classes.home, { [classes.active]: value.startsWith(scRoutingContext.url(react_core_1.SCRoutes.HOME_ROUTE_NAME, {})) }), "aria-label": "Home", to: scRoutingContext.url(react_core_1.SCRoutes.HOME_ROUTE_NAME, {}), component: react_core_1.Link, onClick: handleClickHome }, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "home" }) }))), preferences[react_core_1.SCPreferences.CONFIGURATIONS_EXPLORE_STREAM_ENABLED] &&
155
167
  (preferences[react_core_1.SCPreferences.CONFIGURATIONS_CONTENT_AVAILABILITY] || scUserContext.user) &&
156
168
  (!scUserContext.user || (!groupsEnabled && !coursesEnabled && !eventsEnabled)) && ((0, jsx_runtime_1.jsx)(material_1.IconButton, Object.assign({ className: (0, classnames_1.default)(classes.explore, {
157
169
  [classes.active]: value.startsWith(scRoutingContext.url(react_core_1.SCRoutes.EXPLORE_ROUTE_NAME, {}))
@@ -14,6 +14,7 @@ const NavigationSettingsIconButton_1 = tslib_1.__importDefault(require("../Navig
14
14
  const NavigationMenuIconButton_1 = tslib_1.__importDefault(require("../NavigationMenuIconButton"));
15
15
  const constants_1 = require("./constants");
16
16
  const types_1 = require("@selfcommunity/types");
17
+ const seamless_scroll_polyfill_1 = require("seamless-scroll-polyfill");
17
18
  const ComposerIconButton_1 = tslib_1.__importDefault(require("../ComposerIconButton"));
18
19
  const classes = {
19
20
  root: `${constants_1.PREFIX}-root`,
@@ -101,13 +102,24 @@ function NavigationToolbarMobile(inProps) {
101
102
  const handleCloseSearch = (0, react_1.useCallback)(() => {
102
103
  setSearchOpen(false);
103
104
  }, [setSearchOpen]);
105
+ const handleClickHome = (0, react_1.useCallback)(() => {
106
+ if (onClickHome) {
107
+ onClickHome();
108
+ }
109
+ else {
110
+ const pathName = window.location.pathname;
111
+ if (pathName && (pathName === '/' || pathName === scRoutingContext.url(react_core_1.SCRoutes.HOME_ROUTE_NAME, {}))) {
112
+ (0, seamless_scroll_polyfill_1.scroll)(window, { top: 0, behavior: 'smooth' });
113
+ }
114
+ }
115
+ }, [onClickHome]);
104
116
  // RENDER
105
117
  if (scUserContext.loading) {
106
118
  return (0, jsx_runtime_1.jsx)(Skeleton_1.default, {});
107
119
  }
108
120
  const _children = children || ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(NavigationMenuIconButtonComponent, {}), (0, jsx_runtime_1.jsx)(react_core_1.Link, Object.assign({ to: scRoutingContext.url(react_core_1.SCRoutes.HOME_ROUTE_NAME, {}), className: (0, classnames_1.default)(className, classes.logo, {
109
121
  [classes.logoFlex]: preferences[react_core_1.SCPreferences.CONFIGURATIONS_CUSTOM_NAVBAR_ITEM_URL].value
110
- }) }, (onClickHome && { onClick: onClickHome }), { children: !preserveDesktopLogo ? ((0, jsx_runtime_1.jsx)("img", { src: preferences[react_core_1.SCPreferences.LOGO_NAVBAR_LOGO_MOBILE].value, alt: "logo" })) : ((0, jsx_runtime_1.jsx)("img", { src: preferences[react_core_1.SCPreferences.LOGO_NAVBAR_LOGO].value, alt: "logo" })) })), preferences[react_core_1.SCPreferences.CONFIGURATIONS_CUSTOM_NAVBAR_ITEM_ENABLED].value && ((0, jsx_runtime_1.jsx)(react_core_1.Link, Object.assign({ target: "blank", to: preferences[react_core_1.SCPreferences.CONFIGURATIONS_CUSTOM_NAVBAR_ITEM_URL].value, className: classes.customItem }, { children: (0, jsx_runtime_1.jsx)("img", { src: preferences[react_core_1.SCPreferences.CONFIGURATIONS_CUSTOM_NAVBAR_ITEM_IMAGE].value, alt: "custom_item" }) })))] }));
122
+ }), onClick: handleClickHome }, { children: !preserveDesktopLogo ? ((0, jsx_runtime_1.jsx)("img", { src: preferences[react_core_1.SCPreferences.LOGO_NAVBAR_LOGO_MOBILE].value, alt: "logo" })) : ((0, jsx_runtime_1.jsx)("img", { src: preferences[react_core_1.SCPreferences.LOGO_NAVBAR_LOGO].value, alt: "logo" })) })), preferences[react_core_1.SCPreferences.CONFIGURATIONS_CUSTOM_NAVBAR_ITEM_ENABLED].value && ((0, jsx_runtime_1.jsx)(react_core_1.Link, Object.assign({ target: "blank", to: preferences[react_core_1.SCPreferences.CONFIGURATIONS_CUSTOM_NAVBAR_ITEM_URL].value, className: classes.customItem }, { children: (0, jsx_runtime_1.jsx)("img", { src: preferences[react_core_1.SCPreferences.CONFIGURATIONS_CUSTOM_NAVBAR_ITEM_IMAGE].value, alt: "custom_item" }) })))] }));
111
123
  return ((0, jsx_runtime_1.jsxs)(Root, Object.assign({ className: (0, classnames_1.default)(className, classes.root) }, rest, { children: [_children, startActions, (contentAvailable || scUserContext.user) && !disableSearch && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(material_1.IconButton, Object.assign({ className: classes.search, onClick: handleOpenSearch }, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "search" }) })), (0, jsx_runtime_1.jsx)(SearchDialog_1.default, { className: classes.searchDialog, fullScreen: true, open: searchOpen, SearchAutocompleteComponentProps: Object.assign(Object.assign({}, SearchAutocompleteComponentProps), { onClear: handleCloseSearch }) })] })), endActions, (!postOnlyStaffEnabled || react_core_1.UserUtils.isStaff(scUserContext.user) || react_core_1.UserUtils.isPublisher(scUserContext.user)) &&
112
124
  (scUserContext.user || contentAvailable) &&
113
125
  exploreStreamEnabled && (0, jsx_runtime_1.jsx)(ComposerIconButton_1.default, Object.assign({}, ComposerIconButtonProps)), scUserContext.user && (groupsEnabled || eventsEnabled) && ((0, jsx_runtime_1.jsx)(material_1.IconButton, Object.assign({ className: classes.notifications, component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.USER_NOTIFICATIONS_ROUTE_NAME, {}) }, { children: (0, jsx_runtime_1.jsx)(material_1.Badge, Object.assign({ badgeContent: scUserContext.user.unseen_notification_banners_counter + scUserContext.user.unseen_interactions_counter, color: "secondary" }, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "notifications_active" }) })) }))), scUserContext.user ? ((0, jsx_runtime_1.jsx)(NavigationSettingsIconButtonComponent, { className: classes.settings })) : ((0, jsx_runtime_1.jsx)(material_1.Button, Object.assign({ className: classes.login, color: "inherit", component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.SIGNIN_ROUTE_NAME, {}) }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.appBar.navigation.login", defaultMessage: "ui.appBar.navigation.login" }) })))] })));
@@ -16,7 +16,6 @@ export interface UserAutocompleteProps extends Pick<AutocompleteProps<SCUserAuto
16
16
  * @default 0
17
17
  */
18
18
  limitCountGroups?: number;
19
- endpointQueryParams?: Record<string, string | number | boolean>;
20
19
  }
21
20
  declare const UserAutocomplete: (inProps: UserAutocompleteProps) => JSX.Element;
22
21
  export default UserAutocomplete;
@@ -9,6 +9,7 @@ const match_1 = tslib_1.__importDefault(require("autosuggest-highlight/match"));
9
9
  const material_1 = require("@mui/material");
10
10
  const react_core_1 = require("@selfcommunity/react-core");
11
11
  const system_1 = require("@mui/system");
12
+ const api_services_1 = require("@selfcommunity/api-services");
12
13
  const PREFIX = 'SCUserAutocomplete';
13
14
  const classes = {
14
15
  root: `${PREFIX}-root`,
@@ -39,15 +40,21 @@ const UserAutocomplete = (inProps) => {
39
40
  const [inputValue, setInputValue] = (0, react_1.useState)('');
40
41
  const [value, setValue] = (0, react_1.useState)(Array.isArray(defaultValue) ? defaultValue : defaultValue ? [defaultValue] : []);
41
42
  const [textAreaValue, setTextAreaValue] = (0, react_1.useState)('');
42
- // Fetch users
43
- const { users, isLoading } = (0, react_core_1.useSCFetchUsers)({ search: inputValue });
43
+ // Exclude selected users by ID
44
+ const excludeIds = (0, react_1.useMemo)(() => value
45
+ .map((u) => (typeof u === 'object' ? u.id : null))
46
+ .filter(Boolean)
47
+ .join(','), [value]);
48
+ // Fetch users excluding selected ones
49
+ const { users, isLoading } = (0, react_core_1.useSCFetchUsers)({ search: inputValue, exclude: excludeIds });
50
+ const filteredUsers = users.filter((u) => !excludeIds.includes(u.id));
44
51
  (0, react_1.useEffect)(() => {
45
52
  onChange === null || onChange === void 0 ? void 0 : onChange(value);
46
53
  setTextAreaValue(value.map((u) => (typeof u === 'object' ? u.username : u)).join('\n'));
47
54
  }, [value]);
48
55
  // Handlers
49
56
  const handleOpen = () => {
50
- users.length > 0 && setOpen(true);
57
+ filteredUsers.length > 0 && setOpen(true);
51
58
  };
52
59
  const handleClose = () => {
53
60
  setOpen(false);
@@ -55,26 +62,29 @@ const UserAutocomplete = (inProps) => {
55
62
  const handleChange = (_event, newValue) => {
56
63
  setValue(newValue);
57
64
  };
58
- const handleTextAreaChange = (e) => {
59
- const names = e.target.value
65
+ const handleTextAreaChange = (e) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
66
+ const names = Array.from(new Set(e.target.value
60
67
  .split(/\s|,|\n/)
61
68
  .map((s) => s.trim())
62
- .filter(Boolean);
63
- const matched = names.map((name) => {
64
- const user = users.find((u) => u.username === name);
65
- return user || name;
66
- });
67
- setValue(matched);
69
+ .filter(Boolean)));
70
+ let resolvedUsers = [];
71
+ try {
72
+ if (names.length > 0) {
73
+ const resp = yield api_services_1.UserService.matchUsernames(names.join(','));
74
+ const matchedMap = new Map(resp.map((u) => [u.username, u]));
75
+ resolvedUsers = names.map((name) => matchedMap.get(name) || name);
76
+ }
77
+ }
78
+ catch (err) {
79
+ console.error(`Failed fetching users`, err);
80
+ resolvedUsers = names;
81
+ }
82
+ setValue(resolvedUsers);
68
83
  setTextAreaValue(e.target.value);
69
- };
70
- return ((0, jsx_runtime_1.jsxs)(Root, Object.assign({ className: classes.root }, { children: [(0, jsx_runtime_1.jsx)(AutocompleteRoot, Object.assign({ multiple: true, className: classes.autocompleteRoot, open: open, onOpen: handleOpen, onClose: handleClose, options: users || [], getOptionLabel: (option) => option.username || '', value: value, inputValue: inputValue, onInputChange: (_event, newInputValue) => {
84
+ });
85
+ return ((0, jsx_runtime_1.jsxs)(Root, Object.assign({ className: classes.root }, { children: [(0, jsx_runtime_1.jsx)(AutocompleteRoot, Object.assign({ multiple: true, className: classes.autocompleteRoot, open: open, onOpen: handleOpen, onClose: handleClose, options: filteredUsers || [], getOptionLabel: (option) => option.username || '', value: value, inputValue: inputValue, onInputChange: (_event, newInputValue) => {
71
86
  setInputValue(newInputValue);
72
- }, selectOnFocus: true, clearOnBlur: true, blurOnSelect: true, handleHomeEndKeys: true, clearIcon: null, disabled: disabled || isLoading, noOptionsText: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.userAutocomplete.empty", defaultMessage: "ui.userAutocomplete.empty" }), onChange: handleChange, isOptionEqualToValue: (option, val) => {
73
- if (typeof val === 'string') {
74
- return option.username === val;
75
- }
76
- return option.id === val.id;
77
- }, renderTags: (value, getTagProps) => value.map((option, index) => {
87
+ }, selectOnFocus: true, clearOnBlur: true, blurOnSelect: true, handleHomeEndKeys: true, clearIcon: null, disabled: disabled || isLoading, noOptionsText: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.userAutocomplete.empty", defaultMessage: "ui.userAutocomplete.empty" }), onChange: handleChange, isOptionEqualToValue: (option, val) => option.id === val.id, renderTags: (value, getTagProps) => value.map((option, index) => {
78
88
  const username = typeof option === 'string' ? option : option.username;
79
89
  const avatar = typeof option === 'string' ? '' : option.avatar;
80
90
  const id = typeof option === 'string' ? `fallback-${option}` : option.id;
@@ -1,13 +1,14 @@
1
1
  import { __rest } from "tslib";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { Badge, BottomNavigation as MuiBottomNavigation, BottomNavigationAction, Icon, styled } from '@mui/material';
4
- import { useMemo } from 'react';
4
+ import { useCallback, useMemo } from 'react';
5
5
  import { Link, SCPreferences, SCRoutes, UserUtils, useSCPreferences, useSCRouting, useSCUser } from '@selfcommunity/react-core';
6
6
  import { useThemeProps } from '@mui/system';
7
7
  import classNames from 'classnames';
8
8
  import { SCFeatureName } from '@selfcommunity/types';
9
9
  import { iOS } from '@selfcommunity/utils';
10
10
  import ComposerIconButton from '../ComposerIconButton';
11
+ import { scroll } from 'seamless-scroll-polyfill';
11
12
  const PREFIX = 'SCBottomNavigation';
12
13
  const classes = {
13
14
  root: `${PREFIX}-root`,
@@ -82,11 +83,22 @@ export default function BottomNavigation(inProps) {
82
83
  const postOnlyStaffEnabled = preferences[SCPreferences.CONFIGURATIONS_POST_ONLY_STAFF_ENABLED].value;
83
84
  const contentAvailable = preferences[SCPreferences.CONFIGURATIONS_CONTENT_AVAILABILITY].value;
84
85
  const isIOS = useMemo(() => iOS(), []);
86
+ const handleClickHome = useCallback(() => {
87
+ if (onClickHome) {
88
+ onClickHome();
89
+ }
90
+ else {
91
+ const pathName = window.location.pathname;
92
+ if (pathName && (pathName === '/' || pathName === scRoutingContext.url(SCRoutes.HOME_ROUTE_NAME, {}))) {
93
+ scroll(window, { top: 0, behavior: 'smooth' });
94
+ }
95
+ }
96
+ }, [onClickHome]);
85
97
  // RENDER
86
98
  return (_jsx(Root, Object.assign({ className: classNames(className, classes.root, { [classes.ios]: isIOS }) }, rest, { children: children
87
99
  ? children
88
100
  : [
89
- _jsx(BottomNavigationAction, Object.assign({ className: classes.action, component: Link, to: scUserContext.user ? scRoutingContext.url(SCRoutes.HOME_ROUTE_NAME, {}) : '/', value: scUserContext.user ? scRoutingContext.url(SCRoutes.HOME_ROUTE_NAME, {}) : '/', icon: _jsx(Icon, { children: "home" }) }, (onClickHome && { onClick: onClickHome })), "home"),
101
+ _jsx(BottomNavigationAction, { className: classes.action, component: Link, to: scUserContext.user ? scRoutingContext.url(SCRoutes.HOME_ROUTE_NAME, {}) : '/', value: scUserContext.user ? scRoutingContext.url(SCRoutes.HOME_ROUTE_NAME, {}) : '/', icon: _jsx(Icon, { children: "home" }), onClick: handleClickHome }, "home"),
90
102
  // (scUserContext.user || contentAvailable) && exploreStreamEnabled ? (
91
103
  // <BottomNavigationAction
92
104
  // key="explore"
@@ -3,5 +3,6 @@ import { CategoryProps } from '../Category';
3
3
  export interface DefaultDrawerContentProps extends BoxProps {
4
4
  CategoryItemProps?: CategoryProps;
5
5
  tagImage?: string;
6
+ onClickHome?: () => void;
6
7
  }
7
8
  export default function DefaultDrawerContent(inProps: DefaultDrawerContentProps): JSX.Element;
@@ -2,7 +2,7 @@ import { __rest } from "tslib";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { Box, Divider, Icon, List, ListItem, ListItemButton, ListItemIcon, ListItemText, Typography, Zoom, styled, AccordionDetails, Accordion, AccordionSummary, Avatar } from '@mui/material';
4
4
  import { Link, SCPreferences, SCRoutes, useSCFetchCategories, useSCPreferences, useSCRouting, useSCUser } from '@selfcommunity/react-core';
5
- import { useEffect, useMemo, useState } from 'react';
5
+ import { useCallback, useEffect, useMemo, useState } from 'react';
6
6
  import Category from '../Category';
7
7
  import { FormattedMessage } from 'react-intl';
8
8
  import { sortByAttr } from '@selfcommunity/utils';
@@ -12,6 +12,7 @@ import { useThemeProps } from '@mui/system';
12
12
  import BaseItem from '../../shared/BaseItem';
13
13
  import FormazionePlaceholder from '../../assets/custom/formazione';
14
14
  import { DefaultCategoryTagName } from '../../constants/DefaultDrawerContent';
15
+ import { scroll } from 'seamless-scroll-polyfill';
15
16
  const PREFIX = 'SCDefaultDrawerContent';
16
17
  const classes = {
17
18
  root: `${PREFIX}-root`,
@@ -29,7 +30,7 @@ export default function DefaultDrawerContent(inProps) {
29
30
  props: inProps,
30
31
  name: PREFIX
31
32
  });
32
- const { className, CategoryItemProps = { showTooltip: true }, tagImage = '/' } = props, rest = __rest(props, ["className", "CategoryItemProps", "tagImage"]);
33
+ const { className, CategoryItemProps = { showTooltip: true }, tagImage = '/', onClickHome } = props, rest = __rest(props, ["className", "CategoryItemProps", "tagImage", "onClickHome"]);
33
34
  // HOOKS
34
35
  const { categories } = useSCFetchCategories();
35
36
  const [categoriesOrdered, setCategoriesOrdered] = useState([]);
@@ -77,6 +78,17 @@ export default function DefaultDrawerContent(inProps) {
77
78
  const handleChange = (tagName) => (_event, isExpanded) => {
78
79
  setExpanded(isExpanded ? tagName : false);
79
80
  };
81
+ const handleClickHome = useCallback(() => {
82
+ if (onClickHome) {
83
+ onClickHome();
84
+ }
85
+ else {
86
+ const pathName = window.location.pathname;
87
+ if (pathName && (pathName === '/' || pathName === scRoutingContext.url(SCRoutes.HOME_ROUTE_NAME, {}))) {
88
+ scroll(window, { top: 0, behavior: 'smooth' });
89
+ }
90
+ }
91
+ }, [onClickHome]);
80
92
  // Order categories
81
93
  useEffect(() => {
82
94
  if (!scUserContext.user || (scUserContext.user && showAllCategories)) {
@@ -109,7 +121,7 @@ export default function DefaultDrawerContent(inProps) {
109
121
  }
110
122
  });
111
123
  //order
112
- return (_jsxs(Root, Object.assign({ className: classNames(className, classes.root) }, rest, { children: [_jsxs(List, Object.assign({ className: classes.navigation }, { children: [scUserContext.user && (_jsx(ListItem, Object.assign({ disablePadding: true }, { children: _jsxs(ListItemButton, Object.assign({ component: Link, to: scRoutingContext.url(SCRoutes.HOME_ROUTE_NAME, {}) }, { children: [_jsx(ListItemIcon, { children: _jsx(Icon, { children: "home" }) }), _jsx(ListItemText, { primary: _jsx(FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.home", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.home" }) })] })) }))), coursesEnabled && (scUserContext.user || contentAvailable) && (_jsx(ListItem, Object.assign({ disablePadding: true }, { children: _jsxs(ListItemButton, Object.assign({ component: Link, to: scRoutingContext.url(SCRoutes.COURSES_ROUTE_NAME, {}) }, { children: [_jsx(ListItemIcon, { children: _jsx(Icon, { children: "courses" }) }), _jsx(ListItemText, { primary: _jsx(FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.courses", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.courses" }) })] })) }))), groupsEnabled && scUserContext.user && (_jsx(ListItem, Object.assign({ disablePadding: true }, { children: _jsxs(ListItemButton, Object.assign({ component: Link, to: scRoutingContext.url(SCRoutes.GROUPS_ROUTE_NAME, {}) }, { children: [_jsx(ListItemIcon, { children: _jsx(Icon, { children: "groups" }) }), _jsx(ListItemText, { primary: _jsx(FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.groups", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.groups" }) })] })) }))), eventsEnabled && (scUserContext.user || contentAvailable) && (_jsx(ListItem, Object.assign({ disablePadding: true }, { children: _jsxs(ListItemButton, Object.assign({ component: Link, to: scRoutingContext.url(SCRoutes.EVENTS_ROUTE_NAME, {}) }, { children: [_jsx(ListItemIcon, { children: _jsx(Icon, { children: "CalendarIcon" }) }), _jsx(ListItemText, { primary: _jsx(FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.events", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.events" }) })] })) }))), exploreStreamEnabled && (contentAvailable || scUserContext.user) && (_jsx(ListItem, Object.assign({ disablePadding: true }, { children: _jsxs(ListItemButton, Object.assign({ component: Link, to: scRoutingContext.url(SCRoutes.EXPLORE_ROUTE_NAME, {}) }, { children: [_jsx(ListItemIcon, { children: _jsx(Icon, { children: "explore" }) }), _jsx(ListItemText, { primary: _jsx(FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.explore", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.explore" }) })] })) })))] })), _jsx(Divider, {}), _jsx(Typography, Object.assign({ variant: "subtitle1", className: classes.title }, { children: _jsx(FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.category.title", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.category.title" }) })), !categoriesOrdered.length && (_jsx(Typography, Object.assign({ variant: "body1", className: classes.noResults }, { children: _jsx(FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.category.noResults", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.category.noResults" }) }))), _jsxs(_Fragment, { children: [Object.entries(taggedCategories).map(([tagName, categories]) => {
124
+ return (_jsxs(Root, Object.assign({ className: classNames(className, classes.root) }, rest, { children: [_jsxs(List, Object.assign({ className: classes.navigation }, { children: [scUserContext.user && (_jsx(ListItem, Object.assign({ disablePadding: true }, { children: _jsxs(ListItemButton, Object.assign({ component: Link, to: scRoutingContext.url(SCRoutes.HOME_ROUTE_NAME, {}), onClickHome: handleClickHome }, { children: [_jsx(ListItemIcon, { children: _jsx(Icon, { children: "home" }) }), _jsx(ListItemText, { primary: _jsx(FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.home", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.home" }) })] })) }))), coursesEnabled && (scUserContext.user || contentAvailable) && (_jsx(ListItem, Object.assign({ disablePadding: true }, { children: _jsxs(ListItemButton, Object.assign({ component: Link, to: scRoutingContext.url(SCRoutes.COURSES_ROUTE_NAME, {}) }, { children: [_jsx(ListItemIcon, { children: _jsx(Icon, { children: "courses" }) }), _jsx(ListItemText, { primary: _jsx(FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.courses", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.courses" }) })] })) }))), groupsEnabled && scUserContext.user && (_jsx(ListItem, Object.assign({ disablePadding: true }, { children: _jsxs(ListItemButton, Object.assign({ component: Link, to: scRoutingContext.url(SCRoutes.GROUPS_ROUTE_NAME, {}) }, { children: [_jsx(ListItemIcon, { children: _jsx(Icon, { children: "groups" }) }), _jsx(ListItemText, { primary: _jsx(FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.groups", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.groups" }) })] })) }))), eventsEnabled && (scUserContext.user || contentAvailable) && (_jsx(ListItem, Object.assign({ disablePadding: true }, { children: _jsxs(ListItemButton, Object.assign({ component: Link, to: scRoutingContext.url(SCRoutes.EVENTS_ROUTE_NAME, {}) }, { children: [_jsx(ListItemIcon, { children: _jsx(Icon, { children: "CalendarIcon" }) }), _jsx(ListItemText, { primary: _jsx(FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.events", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.events" }) })] })) }))), exploreStreamEnabled && (contentAvailable || scUserContext.user) && (_jsx(ListItem, Object.assign({ disablePadding: true }, { children: _jsxs(ListItemButton, Object.assign({ component: Link, to: scRoutingContext.url(SCRoutes.EXPLORE_ROUTE_NAME, {}) }, { children: [_jsx(ListItemIcon, { children: _jsx(Icon, { children: "explore" }) }), _jsx(ListItemText, { primary: _jsx(FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.explore", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.navigation.explore" }) })] })) })))] })), _jsx(Divider, {}), _jsx(Typography, Object.assign({ variant: "subtitle1", className: classes.title }, { children: _jsx(FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.category.title", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.category.title" }) })), !categoriesOrdered.length && (_jsx(Typography, Object.assign({ variant: "body1", className: classes.noResults }, { children: _jsx(FormattedMessage, { id: "ui.navigationMenuIconButton.defaultDrawerContent.category.noResults", defaultMessage: "ui.navigationMenuIconButton.defaultDrawerContent.category.noResults" }) }))), _jsxs(_Fragment, { children: [Object.entries(taggedCategories).map(([tagName, categories]) => {
113
125
  var _a;
114
126
  if (!categories.length || !((_a = categories[0].tags) === null || _a === void 0 ? void 0 : _a.length))
115
127
  return null;
@@ -1,7 +1,7 @@
1
1
  import { __rest } from "tslib";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { Avatar, Badge, Box, Button, IconButton, styled, Toolbar, Tooltip, Icon } from '@mui/material';
4
- import React, { useMemo } from 'react';
4
+ import React, { useCallback, useMemo } from 'react';
5
5
  import { useThemeProps } from '@mui/system';
6
6
  import classNames from 'classnames';
7
7
  import NavigationToolbarSkeleton from './Skeleton';
@@ -14,6 +14,7 @@ import { SCFeatureName } from '@selfcommunity/types';
14
14
  import { Link, SCPreferences, SCRoutes, UserUtils, useSCPreferences, useSCRouting, useSCUser } from '@selfcommunity/react-core';
15
15
  import NavigationMenuIconButton from '../NavigationMenuIconButton';
16
16
  import { PREFIX } from './constants';
17
+ import { scroll } from 'seamless-scroll-polyfill';
17
18
  const classes = {
18
19
  root: `${PREFIX}-root`,
19
20
  logo: `${PREFIX}-logo`,
@@ -97,7 +98,7 @@ export default function NavigationToolbar(inProps) {
97
98
  props: inProps,
98
99
  name: PREFIX
99
100
  });
100
- const { value = '', className = '', disableSearch = false, disableComposer = false, SearchAutocompleteComponentProps = {}, startActions = null, endActions = null, NavigationSettingsIconButtonComponent = NavigationSettingsIconButton, NavigationMenuIconButtonComponentProps = {}, NavigationMenuIconButtonComponent = NavigationMenuIconButton, children = null, NotificationMenuProps = {}, ComposerIconButtonProps = {}, onClickHome, onOpenNotificationMenu, onCloseNotificationMenu } = props, rest = __rest(props, ["value", "className", "disableSearch", "disableComposer", "SearchAutocompleteComponentProps", "startActions", "endActions", "NavigationSettingsIconButtonComponent", "NavigationMenuIconButtonComponentProps", "NavigationMenuIconButtonComponent", "children", "NotificationMenuProps", "ComposerIconButtonProps", "onClickHome", "onOpenNotificationMenu", "onCloseNotificationMenu"]);
101
+ const { value = '', className = '', disableSearch = false, disableComposer = false, SearchAutocompleteComponentProps = {}, startActions = null, endActions = null, NavigationSettingsIconButtonComponent = NavigationSettingsIconButton, NavigationMenuIconButtonComponent = NavigationMenuIconButton, NavigationMenuIconButtonComponentProps = {}, children = null, NotificationMenuProps = {}, ComposerIconButtonProps = {}, onClickHome, onOpenNotificationMenu, onCloseNotificationMenu } = props, rest = __rest(props, ["value", "className", "disableSearch", "disableComposer", "SearchAutocompleteComponentProps", "startActions", "endActions", "NavigationSettingsIconButtonComponent", "NavigationMenuIconButtonComponent", "NavigationMenuIconButtonComponentProps", "children", "NotificationMenuProps", "ComposerIconButtonProps", "onClickHome", "onOpenNotificationMenu", "onCloseNotificationMenu"]);
101
102
  // CONTEXT
102
103
  const scUserContext = useSCUser();
103
104
  const scRoutingContext = useSCRouting();
@@ -145,11 +146,22 @@ export default function NavigationToolbar(inProps) {
145
146
  setAnchorNotification(null);
146
147
  onCloseNotificationMenu && onCloseNotificationMenu();
147
148
  };
149
+ const handleClickHome = useCallback(() => {
150
+ if (onClickHome) {
151
+ onClickHome();
152
+ }
153
+ else {
154
+ const pathName = window.location.pathname;
155
+ if (pathName && (pathName === '/' || pathName === scRoutingContext.url(SCRoutes.HOME_ROUTE_NAME, {}))) {
156
+ scroll(window, { top: 0, behavior: 'smooth' });
157
+ }
158
+ }
159
+ }, [onClickHome]);
148
160
  // RENDER
149
161
  if (scUserContext.loading) {
150
162
  return _jsx(NavigationToolbarSkeleton, {});
151
163
  }
152
- const _children = children || (_jsxs(Box, Object.assign({ className: classes.navigation }, { children: [scUserContext.user && (_jsx(IconButton, Object.assign({ className: classNames(classes.home, { [classes.active]: value.startsWith(scRoutingContext.url(SCRoutes.HOME_ROUTE_NAME, {})) }), "aria-label": "Home", to: scRoutingContext.url(SCRoutes.HOME_ROUTE_NAME, {}), component: Link }, (onClickHome && { onClick: onClickHome }), { children: _jsx(Icon, { children: "home" }) }))), preferences[SCPreferences.CONFIGURATIONS_EXPLORE_STREAM_ENABLED] &&
164
+ const _children = children || (_jsxs(Box, Object.assign({ className: classes.navigation }, { children: [scUserContext.user && (_jsx(IconButton, Object.assign({ className: classNames(classes.home, { [classes.active]: value.startsWith(scRoutingContext.url(SCRoutes.HOME_ROUTE_NAME, {})) }), "aria-label": "Home", to: scRoutingContext.url(SCRoutes.HOME_ROUTE_NAME, {}), component: Link, onClick: handleClickHome }, { children: _jsx(Icon, { children: "home" }) }))), preferences[SCPreferences.CONFIGURATIONS_EXPLORE_STREAM_ENABLED] &&
153
165
  (preferences[SCPreferences.CONFIGURATIONS_CONTENT_AVAILABILITY] || scUserContext.user) &&
154
166
  (!scUserContext.user || (!groupsEnabled && !coursesEnabled && !eventsEnabled)) && (_jsx(IconButton, Object.assign({ className: classNames(classes.explore, {
155
167
  [classes.active]: value.startsWith(scRoutingContext.url(SCRoutes.EXPLORE_ROUTE_NAME, {}))
@@ -12,6 +12,7 @@ import NavigationSettingsIconButton from '../NavigationSettingsIconButton';
12
12
  import NavigationMenuIconButton from '../NavigationMenuIconButton';
13
13
  import { PREFIX } from './constants';
14
14
  import { SCFeatureName } from '@selfcommunity/types';
15
+ import { scroll } from 'seamless-scroll-polyfill';
15
16
  import ComposerIconButton from '../ComposerIconButton';
16
17
  const classes = {
17
18
  root: `${PREFIX}-root`,
@@ -99,13 +100,24 @@ export default function NavigationToolbarMobile(inProps) {
99
100
  const handleCloseSearch = useCallback(() => {
100
101
  setSearchOpen(false);
101
102
  }, [setSearchOpen]);
103
+ const handleClickHome = useCallback(() => {
104
+ if (onClickHome) {
105
+ onClickHome();
106
+ }
107
+ else {
108
+ const pathName = window.location.pathname;
109
+ if (pathName && (pathName === '/' || pathName === scRoutingContext.url(SCRoutes.HOME_ROUTE_NAME, {}))) {
110
+ scroll(window, { top: 0, behavior: 'smooth' });
111
+ }
112
+ }
113
+ }, [onClickHome]);
102
114
  // RENDER
103
115
  if (scUserContext.loading) {
104
116
  return _jsx(NavigationToolbarMobileSkeleton, {});
105
117
  }
106
118
  const _children = children || (_jsxs(_Fragment, { children: [_jsx(NavigationMenuIconButtonComponent, {}), _jsx(Link, Object.assign({ to: scRoutingContext.url(SCRoutes.HOME_ROUTE_NAME, {}), className: classNames(className, classes.logo, {
107
119
  [classes.logoFlex]: preferences[SCPreferences.CONFIGURATIONS_CUSTOM_NAVBAR_ITEM_URL].value
108
- }) }, (onClickHome && { onClick: onClickHome }), { children: !preserveDesktopLogo ? (_jsx("img", { src: preferences[SCPreferences.LOGO_NAVBAR_LOGO_MOBILE].value, alt: "logo" })) : (_jsx("img", { src: preferences[SCPreferences.LOGO_NAVBAR_LOGO].value, alt: "logo" })) })), preferences[SCPreferences.CONFIGURATIONS_CUSTOM_NAVBAR_ITEM_ENABLED].value && (_jsx(Link, Object.assign({ target: "blank", to: preferences[SCPreferences.CONFIGURATIONS_CUSTOM_NAVBAR_ITEM_URL].value, className: classes.customItem }, { children: _jsx("img", { src: preferences[SCPreferences.CONFIGURATIONS_CUSTOM_NAVBAR_ITEM_IMAGE].value, alt: "custom_item" }) })))] }));
120
+ }), onClick: handleClickHome }, { children: !preserveDesktopLogo ? (_jsx("img", { src: preferences[SCPreferences.LOGO_NAVBAR_LOGO_MOBILE].value, alt: "logo" })) : (_jsx("img", { src: preferences[SCPreferences.LOGO_NAVBAR_LOGO].value, alt: "logo" })) })), preferences[SCPreferences.CONFIGURATIONS_CUSTOM_NAVBAR_ITEM_ENABLED].value && (_jsx(Link, Object.assign({ target: "blank", to: preferences[SCPreferences.CONFIGURATIONS_CUSTOM_NAVBAR_ITEM_URL].value, className: classes.customItem }, { children: _jsx("img", { src: preferences[SCPreferences.CONFIGURATIONS_CUSTOM_NAVBAR_ITEM_IMAGE].value, alt: "custom_item" }) })))] }));
109
121
  return (_jsxs(Root, Object.assign({ className: classNames(className, classes.root) }, rest, { children: [_children, startActions, (contentAvailable || scUserContext.user) && !disableSearch && (_jsxs(_Fragment, { children: [_jsx(IconButton, Object.assign({ className: classes.search, onClick: handleOpenSearch }, { children: _jsx(Icon, { children: "search" }) })), _jsx(SearchDialog, { className: classes.searchDialog, fullScreen: true, open: searchOpen, SearchAutocompleteComponentProps: Object.assign(Object.assign({}, SearchAutocompleteComponentProps), { onClear: handleCloseSearch }) })] })), endActions, (!postOnlyStaffEnabled || UserUtils.isStaff(scUserContext.user) || UserUtils.isPublisher(scUserContext.user)) &&
110
122
  (scUserContext.user || contentAvailable) &&
111
123
  exploreStreamEnabled && _jsx(ComposerIconButton, Object.assign({}, ComposerIconButtonProps)), scUserContext.user && (groupsEnabled || eventsEnabled) && (_jsx(IconButton, Object.assign({ className: classes.notifications, component: Link, to: scRoutingContext.url(SCRoutes.USER_NOTIFICATIONS_ROUTE_NAME, {}) }, { children: _jsx(Badge, Object.assign({ badgeContent: scUserContext.user.unseen_notification_banners_counter + scUserContext.user.unseen_interactions_counter, color: "secondary" }, { children: _jsx(Icon, { children: "notifications_active" }) })) }))), scUserContext.user ? (_jsx(NavigationSettingsIconButtonComponent, { className: classes.settings })) : (_jsx(Button, Object.assign({ className: classes.login, color: "inherit", component: Link, to: scRoutingContext.url(SCRoutes.SIGNIN_ROUTE_NAME, {}) }, { children: _jsx(FormattedMessage, { id: "ui.appBar.navigation.login", defaultMessage: "ui.appBar.navigation.login" }) })))] })));
@@ -16,7 +16,6 @@ export interface UserAutocompleteProps extends Pick<AutocompleteProps<SCUserAuto
16
16
  * @default 0
17
17
  */
18
18
  limitCountGroups?: number;
19
- endpointQueryParams?: Record<string, string | number | boolean>;
20
19
  }
21
20
  declare const UserAutocomplete: (inProps: UserAutocompleteProps) => JSX.Element;
22
21
  export default UserAutocomplete;
@@ -1,12 +1,13 @@
1
- import { __rest } from "tslib";
1
+ import { __awaiter, __rest } from "tslib";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import React, { Fragment, useEffect, useState } from 'react';
3
+ import React, { Fragment, useEffect, useMemo, useState } from 'react';
4
4
  import { FormattedMessage } from 'react-intl';
5
5
  import parse from 'autosuggest-highlight/parse';
6
6
  import match from 'autosuggest-highlight/match';
7
7
  import { Autocomplete, Chip, TextField, CircularProgress, styled, Avatar, Box, Typography, Icon } from '@mui/material';
8
8
  import { useSCFetchUsers } from '@selfcommunity/react-core';
9
9
  import { useThemeProps } from '@mui/system';
10
+ import { UserService } from '@selfcommunity/api-services';
10
11
  const PREFIX = 'SCUserAutocomplete';
11
12
  const classes = {
12
13
  root: `${PREFIX}-root`,
@@ -37,15 +38,21 @@ const UserAutocomplete = (inProps) => {
37
38
  const [inputValue, setInputValue] = useState('');
38
39
  const [value, setValue] = useState(Array.isArray(defaultValue) ? defaultValue : defaultValue ? [defaultValue] : []);
39
40
  const [textAreaValue, setTextAreaValue] = useState('');
40
- // Fetch users
41
- const { users, isLoading } = useSCFetchUsers({ search: inputValue });
41
+ // Exclude selected users by ID
42
+ const excludeIds = useMemo(() => value
43
+ .map((u) => (typeof u === 'object' ? u.id : null))
44
+ .filter(Boolean)
45
+ .join(','), [value]);
46
+ // Fetch users excluding selected ones
47
+ const { users, isLoading } = useSCFetchUsers({ search: inputValue, exclude: excludeIds });
48
+ const filteredUsers = users.filter((u) => !excludeIds.includes(u.id));
42
49
  useEffect(() => {
43
50
  onChange === null || onChange === void 0 ? void 0 : onChange(value);
44
51
  setTextAreaValue(value.map((u) => (typeof u === 'object' ? u.username : u)).join('\n'));
45
52
  }, [value]);
46
53
  // Handlers
47
54
  const handleOpen = () => {
48
- users.length > 0 && setOpen(true);
55
+ filteredUsers.length > 0 && setOpen(true);
49
56
  };
50
57
  const handleClose = () => {
51
58
  setOpen(false);
@@ -53,26 +60,29 @@ const UserAutocomplete = (inProps) => {
53
60
  const handleChange = (_event, newValue) => {
54
61
  setValue(newValue);
55
62
  };
56
- const handleTextAreaChange = (e) => {
57
- const names = e.target.value
63
+ const handleTextAreaChange = (e) => __awaiter(void 0, void 0, void 0, function* () {
64
+ const names = Array.from(new Set(e.target.value
58
65
  .split(/\s|,|\n/)
59
66
  .map((s) => s.trim())
60
- .filter(Boolean);
61
- const matched = names.map((name) => {
62
- const user = users.find((u) => u.username === name);
63
- return user || name;
64
- });
65
- setValue(matched);
67
+ .filter(Boolean)));
68
+ let resolvedUsers = [];
69
+ try {
70
+ if (names.length > 0) {
71
+ const resp = yield UserService.matchUsernames(names.join(','));
72
+ const matchedMap = new Map(resp.map((u) => [u.username, u]));
73
+ resolvedUsers = names.map((name) => matchedMap.get(name) || name);
74
+ }
75
+ }
76
+ catch (err) {
77
+ console.error(`Failed fetching users`, err);
78
+ resolvedUsers = names;
79
+ }
80
+ setValue(resolvedUsers);
66
81
  setTextAreaValue(e.target.value);
67
- };
68
- return (_jsxs(Root, Object.assign({ className: classes.root }, { children: [_jsx(AutocompleteRoot, Object.assign({ multiple: true, className: classes.autocompleteRoot, open: open, onOpen: handleOpen, onClose: handleClose, options: users || [], getOptionLabel: (option) => option.username || '', value: value, inputValue: inputValue, onInputChange: (_event, newInputValue) => {
82
+ });
83
+ return (_jsxs(Root, Object.assign({ className: classes.root }, { children: [_jsx(AutocompleteRoot, Object.assign({ multiple: true, className: classes.autocompleteRoot, open: open, onOpen: handleOpen, onClose: handleClose, options: filteredUsers || [], getOptionLabel: (option) => option.username || '', value: value, inputValue: inputValue, onInputChange: (_event, newInputValue) => {
69
84
  setInputValue(newInputValue);
70
- }, selectOnFocus: true, clearOnBlur: true, blurOnSelect: true, handleHomeEndKeys: true, clearIcon: null, disabled: disabled || isLoading, noOptionsText: _jsx(FormattedMessage, { id: "ui.userAutocomplete.empty", defaultMessage: "ui.userAutocomplete.empty" }), onChange: handleChange, isOptionEqualToValue: (option, val) => {
71
- if (typeof val === 'string') {
72
- return option.username === val;
73
- }
74
- return option.id === val.id;
75
- }, renderTags: (value, getTagProps) => value.map((option, index) => {
85
+ }, selectOnFocus: true, clearOnBlur: true, blurOnSelect: true, handleHomeEndKeys: true, clearIcon: null, disabled: disabled || isLoading, noOptionsText: _jsx(FormattedMessage, { id: "ui.userAutocomplete.empty", defaultMessage: "ui.userAutocomplete.empty" }), onChange: handleChange, isOptionEqualToValue: (option, val) => option.id === val.id, renderTags: (value, getTagProps) => value.map((option, index) => {
76
86
  const username = typeof option === 'string' ? option : option.username;
77
87
  const avatar = typeof option === 'string' ? '' : option.avatar;
78
88
  const id = typeof option === 'string' ? `fallback-${option}` : option.id;